views:

58

answers:

3

Hello,

In Rails 3, I created a Search Form that does a FIND with conditions in the Models file.

  @projects = find(:all,
                :select => 'projects.*',
                :conditions => ['name = ?', search_name]
                ).first

This works great if a name is provided in the searchform (search_name). Problem is if search_name is blank, Rails Errors (can't say I blame it)...

What is the smart way to handle this situation? I'd like, if search_name is blank, to not error but return everything.

Suggestions? Thanks!

+3  A: 
if search_name.blank?
  @projects = Project.order(:name)
else
  @projects = Project.where(:name => search_name)
end
bensie
I considered that but thought perhaps there was a cleaner Rails type solution?
AnApprentice
`@projects = (search_name.blank? Project.order(:name) : Project.where(:name => search_name) )` :)
Joe
I would say that using ternary here is pretty ugly but if you want a one-liner, go for it.
bensie
+1  A: 

The cleanest way is using lazy loading with the new ActiveRecord functionalities like this:

@projects = Project.order(:name) @projects = @projects.where(:name => search_name) if search_name

You can add as many conditions as you like this way. They won't be executed until you need the results anyway (with @projects.all or @projects.each, etc...)

Abel Tamayo
Lazy loading is ideal, but in this case it would also perform the ORDER BY on the name column, which may not be desirable in search. Very new in Rails master, they've added the except() method, which could be used for .except(:order)...
bensie
+5  A: 

You can create a scope to handle this. In your Project model, add something like:

scope :search_by(name), lambda{|name| first.where(:name => name) unless name.blank?}

then in your controller, simply call:

Project.search_by(params[:search])

EDIT:

If you need to serach for multiple fields you can adapt the scope:

scope :search_by(name), lambda{|name| first.includes(:owner).where("projects.name LIKE ? OR owners.name LIKE ?", name, name) unless name.blank?}

Yannis
Very elegant. What is My Project search is by multiple fields like (Owner, Name, Created Date) and only Name is optional?
AnApprentice
should it not be "scope :search_by(name), lambda{|name| first.where(:name => name) unless name.blank?}" ?
ipsum
Your right ipsum… corrected!
Yannis
TheApprentice: of course, you can set the scope to fit your needs
Yannis
Interesting what happens if name is blank? Don't you want to return something. In this case?
WozPoz