This blog post解释了如何根据此代码中的参数进行过滤。
def index
@products = Product.where(nil) # creates an anonymous scope
@products = @products.status(params[:status]) if params[:status].present?
@products = @products.location(params[:location]) if params[:location].present?
@products = @products.starts_with(params[:starts_with]) if params[:starts_with].present?
end
Product.where(nil)
解决方案的一部分是有问题的,因为它会将所有内容加载到内存中,如果模型很大,会导致服务器崩溃。
其中一篇博文评论者说:“用Product.none
代替Product.where(nil)
不是更好吗?”但我无法让这个解决方案奏效。
This Stackoverflow answer通过ActiveRecord::Relation
方法访问joins
对象。我没有加入,所以这个解决方案对我不起作用。
让我知道,如果有更好的方法来做到这一点或完全不同的方式我应该解决这个问题。谢谢!
你可以这样做:
def index
[:status, :location, :starts_with].each do |param_sym|
@products = (@products ? @products : Product).send(param_sym, params[param_sym]) if params[param_sym].present?
end
end
为什么不使用.all
并合并其他范围?
def filter_by_params
params.slice(:status, :location, :starts_with)
.compact # removes keys with nil values
# iterates though the hash and returns a scope
.each_with_object(Product.all) do |(key, value), scope|
scope.merge(Product.send(key, value))
end
end