views:

407

answers:

5

I want to make a SQL query in a Rails app that adds a condition when a drop-down menu is added. Obviously I don't want to search with a blank condition if the drop down is not selected. How can I develop a dynamic condition in an SQL statement?

untested example:

When dropdown is not selected: Object.find("billy," :conditions => {})

When dropdown is selected: Object.find("billy," :conditions => {"last_name => "johnson"})

Thank you for your input!

A: 

You could build a conditions hash and just pass it in...

Jason Punyon
No offense, but I don't think rubynube knows enough about Ruby to understand what you mean by this answer.
Topher Fangio
@Topher Fangio: Gotta learn sometime :) I'd UV the "How do I build a hash in ruby?" follow up.
Jason Punyon
Speaking of learning...what do you mean by "UV"? :-)
Topher Fangio
@Topher Fangio: Up Vote
Jason Punyon
+1  A: 

Maybe this?

Object.find("billy", :conditions => last_name.nil? ? {} : {:last_name => last_name})
+3  A: 

Not quite sure what you are doing, but the general way to achieve this is to have the drop-down's value (not visible text) be the ID of the object you wish to select. If you don't have a selection then you can use something like this:

last_name = unless params[:object][:last_name]

conditions = []
conditions << "last_name = ?" unless last_name.blank?
conditions << last_name unless last_name.blank?

Object.find("billy", :conditions => conditions)

Check out this link to learn more about ActiveRecord::Base.find() methods and the proper way to use them. Also look at this great guide to learn how to protect yourself from SQL injection attacks.

Edit 1: Modified code to be cleaner. This method also has the advantage of being able to easily add separate conditionals, just make sure that you add all of the "something = ?" before you add the associated value (param).

Edit 2: In case you haven't seen the select form helper, you might consider using it for your drop down. Makes life a lot easier :-)

Topher Fangio
I dunno if I stole "last_name => ?" from your code or adapted it from the question. Either way my proof-reading sucks! Thanks for pointing it out.
Mike Woodhouse
Lol, we probably both looked at the original code...I hadn't even noticed it was wrong there too.
Topher Fangio
+3  A: 

Assuming your #find is in a controller and that the value selected is coming in as an item in params (and I think you should consider changing things if not!) then you should be able to do something like this:

if params[:last_name] # or whatever it's actually called
  Object.find("billy," :conditions => {'last_name = ?', params[:last_name]})
else
  Object.find("billy")
end

If you're using a reasonably recent version of ActiveRecord (2.1 should do it, possibly 2.0) then you might shift that logic down to a named_scope:

class Object < ActiveRecord::Base
  named_scope :for_last_name, lambda { |nm| { :conditions => nm.nil? ? {} : { last_name => nm } }

and then your controller boils down to (and we love thin controllers)

Object.for_last_name(params[:last_name])

(All somewhat untested)

Mike Woodhouse
He he, you must have looked at my code and used "last_name => ?" instead of "last_name = ?". Sorry to throw you off, I fixed mine :-)
Topher Fangio
Agreed on using named_scopes when attempting to handle dynamic conditions
Scott
A: 

I'm using SmartTuple for that. It's simple, yet offers a systematic approach to building "conditional conditions".

dadooda