Rails 3使用作用域进行多参数过滤



尝试在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)

最新更新