快速举例,
@user = User.all
@user = @user.where(live: true) if params[:live]
@user = @user.where(another: true) if params[:another]
@user = @user.where(another2: true) if params[:another2]
@user = @user.where(another3: true) if params[:another3]
.
.
.
如果有很多参数
,这段代码会对数据库产生很大的影响所以我正在考虑将搜索条件保存到var并在最终执行它。
where_condition += '.where(live: true)' if params[:live]
where_condition += @user.where(another: true) if params[:another]
where_condition += @user.where(another2: true) if params[:another2]
where_condition += @user.where(another3: true) if params[:another3]
.
.
.
@user = User.all.where_condition
有这样的好解决方案吗?
答案 0 :(得分:2)
Rails使用ActiveRecord关系的延迟评估,因此在评估查询时,您的代码不会多次命中数据库,但只会命中一次。
您可以通过查看日志轻松查看。您会注意到查询只执行一次。
因此,您的代码很好。不过,您可以采用一些改进措施。第一个是使用!
方法来链接条件。
而不是
@user = User.all
@user = @user.where(live: true) if params[:live]
@user = @user.where(another: true) if params[:another]
...
你可以使用
@user = User.all
@user.where!(live: true) if params[:live]
@user.where!(another: true) if params[:another]
第二个问题是,你绝对应该避免直接在控制器中建立一系列条件,因为这会使你的代码很难被测试。为了测试查询的成功执行,您必须构建一个完整的控制器测试。
在模型方法中重构代码。
class User
def self.search(params)
scope = all
scope.where!(live: true) if params[:live]
# ...
scope
end
end
在您的控制器中
@users = User.search(params)
这将使您的模型和控制器的单元测试更容易,因为您可以独立测试它们。在很长一段时间内,代码也更易于维护。
答案 1 :(得分:0)
它没有经常访问数据库,它只进行一次查询。澄清一下,我在谈论这个:
@user = User.all
@user = @user.where(live: true) if params[:live]
@user = @user.where(another: true) if params[:another]
@user = @user.where(another2: true) if params[:another2]
@user = @user.where(another3: true) if params[:another3]
.
.
.
通过Rails控制台运行给定代码时,您可能会有这种感觉。问题是您的应用程序中的行为略有不同。逐行评估给定代码时,您将获得@user
的中间值(因为这是分配返回的内容),控制台将尝试inspect
它供您检查,因此,执行每个查询。
您的应用程序代码不会这样做,因为它不会在交互式会话中运行。
ActiveRecord关系 lazy :因此,除非您通过inspect
,each
或任何其他需要实际数据的方法请求数据,否则它们不会执行。 where
没有。
你可以在这里使用一些重构,因为if
s的船只不会干,但它会起作用。
答案 2 :(得分:0)
试一试 -
@user = User.all
@user = @user.select {|u| (params[:live] ? u.live : true) && (params[:another] ? u.another : true) && (params[:another2] ? u.another2 : true)}