尝试在rails 3中使用url参数做一个基本的过滤器。我想有一个白名单的参数,可以通过过滤,并返回所有匹配的项目。我已经设置了一些作用域(以后还会有更多):
# in the model:
scope :budget_min, lambda {|min| where("budget > ?", min)}
scope :budget_max, lambda {|max| where("budget < ?", max)}
…但是,基于当前的params[]
,使用部分、全部或全部作用域的最佳方法是什么?我已经说了这么多,但它并没有扩展到多种选择。寻找一种"chain if present"类型的操作
@jobs = Job.all
@jobs = Job.budget_min(params[:budget_min]) if params[:budget_min]
我想你很接近了。像这样的东西不会扩展到多个选项吗?
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
一般来说,我更喜欢手工制作的解决方案,但是对于这类问题,代码库可能很快就会变得一团糟。所以我会选择meta_search。
一种方法是将条件放入作用域:
scope :budget_max, lambda { |max| where("budget < ?", max) unless max.nil? }
这仍然会变得相当麻烦,因为你最终会得到:
Job.budget_min(params[:budget_min]).budget_max(params[:budget_max]) ...
一个稍微不同的方法是在你的模型中使用下面的东西(基于这里的代码):
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
然后你可以像下面这样使用这个方法,它应该使用白名单过滤器,如果它们出现在参数中:
MyModel.search(params)