Wednesday, June 27, 2007

Using ez_where

While reading the documentation for the ez_where plugin in rails I got a little confused as I am a noob to rails. So once I figured out how to use this plugin I was able to develop tests and search functionality for an eight field search in under 5 hours. This was amazing to me coming from a classic asp background where this type of functionality would have taken a few days at least since some of the relationships would have required a very complex sql statement. But enough of my rambling lets get to the code.....

First off you'll want to get the ez_where plugin (http://opensvn.csie.org/ezra/rails/plugins/dev/ez_where/) inside the readme file the author provides several examples that are great and what I based my search off of. The nice part about this plugin is the way it extends active record. Rather then doing a Class.find(:all) you use Class.ez_find(:all) these will return the same results the fun part comes when you have two tables with related data that you want to search on. I'm going to use the authors examples and explain them a little more so thanks to Ezra Zygmuntowicz & Fabien Franzen for this great plugin.

First example:

articles = Article.ez_find(:all, :include => :author) do |article, author|
article.title =~ "%Foo Title%"
author.any do
name == 'Ezra'
name == 'Fab'
end
end

So first off we have the variable that we want to store the results in, in this case were looking for articles so were going to search using the main class of Article by implementing the ez_find method we are looking for all articles and also including the author association. This is what got me confused, as I stated I come from a procedural programming background using classic asp and the way I would have done this in asp would have been to write a humongous sql statement to search across the tables. So when I was reading the example I mistook the include => author for include the author table not the association that article. This was the biggest thing that I struggled with. So drop your associations in place and then build your logic for the search. I'm going to include my search as another example of how to implement this plugin.


def self.search(params)@alum = Alum.ez_find(:all,
:include => [:majors, :minors, :industry, :job_function])
do |alums, majors, minors, industry, job_function|
unless params[:search][:major].nil?
majors.id == params[:search][:major]
end

unless params[:search][:minor].nil?
minors.id == params[:search][:minor]
end

unless params[:search][:industry].nil?
industry.id == params[:search][:industry]
end

unless params[:search][:job_function].nil?
job_function.id == params[:search][:job_function]
end

unless params[:search][:employer].nil?
alums.employer == params[:search][:employer]
end

unless params[:search][:city].nil?
alums.city == params[:search][:city]
end

unless params[:search][:state].nil?
alums.state == params[:search][:state]
end
end
end


And now a test case example:

def test_search_for_employer_dimeo_family
alum = Alum.search(:search => {:employer => "DiMeo Family"})
assert_equal(3, alum.size)
assert alum.detect {|a| a.first_name == "Tony"}
assert alum.detect {|a| a.first_name == "Bobby"}
assert alum.detect {|a| a.first_name == "Christopher"}
end

And Finally the controller action:

def search_results
@alums = Alum.search(params)
render :action => "list"
end
There you have it, another example and my two cents.

Enjoy!
-CH