This function in my Profile
model receive a hash from a search form and should filter the table depending on those values. I guess there is something like a pattern for such a standard behavior, right now I ended up with this (unfortunately I had to reproduce the code here, so it might not work for some reasons, but you get the idea).
Just a note: we're storing in the model some strings containing multiple data, each of these fields should be a one-to-many relationship (db normality violation). I give an example: country_preferences
is a string filled up by an html select :multiple => true
. In the string I then find values like: ["Australia", "China", "United Kingdom"]
.
def search opts # This default doesn't work the way I would like = {:user_type => :family}
#TODO: default opts value in method sign if possible
opts[:user_type] ||= :family
# initial criteria
fields= "user_type= ?"
values= [opts[:user_type]]
# each field filters the list in one of these three ways
staight_fields = [ :country, :first_name, :last_name, :nationality ]
like_fields = [:country_preferences, :keyword, :languages ]
bool_fields = [:driver, :housework, :children ]
# cicle the options and build the query
opts.each do |k, v|
if straight_fields.include? k
fields += " AND #{k} = ?"
values += v
elsif like_fields.include? k
fields += " AND #{k} like %?%"
values += v
elsif bool_fields.include? k
fields += " AND #{k} = ?"
values += v == 'true'
else
logger.warn "opts #{k} with value #{v} ignored from search"
end
end
# execute the query and return the result
self.registered.actives.where([fields] + values)
end
I think I can use more scope
but how can I combine them together? In general, how can I make this code much better?
The boss, when introducing the project, said one-to-many relationships for that kind of fields would be a pain in the back. What do you think about this pragmatic solution?
profiles =
at the beginning of every line after the first and a finalprofiles
at the end of the method. \$\endgroup\$