Variable numbers of terms in a query

Ruby is your friend. I'm going to assume that you are receiving this in params in an action something like this:

params["db_terms"] = {   "a" => { "oper" => ">", "value" => "1" },   "b" => { "oper" => "=", "value" => "2" },   "c" => { "oper" => ">=", "value" => "3" } }

I'm also assuming you have a canonical list of acceptable field names (as strings) in a constant named KnownFields and a similar list of acceptable operators (as strings) in KnownOperators. Since we need a dependable (but not necessarily sorted) order, we'll turn it into an array instead of a hash first, then produce a condition string:

db_terms = params[:db_terms].select { |field,condition|   KnownFields.include?(field) &&     Hash === condition &&     KnownOperators.include?(condition["oper"]) &&     !condition["value"].blank? }

If a value or operator is missing or left empty or an unknown field or operator is maliciously inserted in the query params, this will get rid of that part of the query. Next is the easy part:

if db_terms.empty?   # What do you do when no valid conditions are given? else   condition_string = db_terms.map { |field,condition|     "#{field} #{condition['oper'] ?" }.join(' AND ')   condition_values = db_terms.map { |field,condition| condition['value'] }   @things = Thing.find :all,     :conditions => [ "#{condition_string} AND foreign_key_id IS NOT NULL",                      *condition_values ] end

--Greg

[...]

The idea of params[:param_sym][param] is so that only allowed operators from a set of radio button options can be selected, which are defined in the view. The bit in escapted single quotes is the text from the user. I then join findarray on " and " and insert it into the search string.

You can't trust anything coming to you over the net. It doesn't matter if you only have radio buttons with acceptable values in the HTML you send. Any malicious user can send any data whatsoever in your params. You must always validate on the server side regardless of any validation or restrictions you have in HTML or JS.

Your system looks rather less crude than mine, so I'll give it a try. Many thanks.

Good luck.

--Greg