当大型模型存在param时Rails过滤

此博客文章介绍了如何根据此代码中的参数进行过滤。

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)是不是更好?” 但我无法让这个解决方案奏效。

此Stackoverflow应答通过joins方法访问ActiveRecord::Relation对象。 我没有加入,所以这个解决方案对我不起作用。

让我知道如果有更好的方法来完成这个或完全不同的方式我应该解决这个问题。 谢谢!

你可以这样做:

 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