+4  A: 

I recently solved a similar problem using named_scopes and some ruby metaprogramming that I rolled up into a plugin called find_by_filter.

find_by_filter accepts a hash of scope names and values, and chains them into parametised scope calls. If the model has a named_scope that matches the provided name, this is called.If no named_scope is found, an anonymous scope is created.

Toby Hede
Cool! Does find_by_filter deal with SQL injection etc?
Horace Loeb
Parameters are bound in your named scopes - so if you handle that correctly you should be fine. The internals are quite simple - feel free to just rip off the idea :P.Scopes can be chained to form complex queries - that's really the core of the approach.I also validate against anticipated filter options (using something like "if accepted.include?(params[:filter])" where accepted is an array of accepted strings.
Toby Hede