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