可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Trying to do a basic filter in rails 3 using the url params. I'd like to have a white list of params that can be filtered by, and return all the items that match. I've set up some scopes (with many more to come):
# in the model: scope :budget_min, lambda {|min| where("budget > ?", min)} scope :budget_max, lambda {|max| where("budget < ?", max)}
...but what's the best way to use some, none, or all of these scopes based on the present params[]
? I've gotten this far, but it doesn't extend to multiple options. Looking for a sort of "chain if present" type operation.
@jobs = Job.all @jobs = Job.budget_min(params[:budget_min]) if params[:budget_min]
回答1:
I think you are close. Something like this won't extend to multiple options?
query = Job.scoped query = query.budget_min(params[:budget_min]) if params[:budget_min] query = query.budget_max(params[:budget_max]) if params[:budget_max] @jobs = query.all
回答2:
Generally, I'd prefer hand-made solutions but, for this kind of problem, a code base could become a mess very quickly. So I would go for a gem like meta_search.
回答3:
One way would be to put your conditionals into the scopes:
scope :budget_max, lambda { |max| where("budget < ?", max) unless max.nil? }
That would still become rather cumbersome since you'd end up with:
Job.budget_min(params[:budget_min]).budget_max(params[:budget_max]) ...
A slightly different approach would be using something like the following inside your model (based on code from here:
class << self def search(q) whitelisted_params = { :budget_max => "budget > ?", :budget_min => "budget < ?" } whitelisted_params.keys.inject(scoped) do |combined_scope, param| if q[param].nil? combined_scope else combined_scope.where(whitelisted_params[param], q[param]) end end end end
You can then use that method as follows and it should use the whitelisted filters if they're present in params:
MyModel.search(params)