我有一个方法(如下所示)有很多查询。我该如何优化呢?
def index
@users = User.all
@admin_users = User.where(role: 'admin')
@call_users = User.where(role: 'call_user')
@buy_users = User.where(role: 'buy_user')
@blocked_users = User.where(role: 'blocked_user')
end
答案 0 :(得分:1)
所有这些都取决于如何定义视图页面,如果在视图页面中用户可以按不同的角色排序,那么它可以写为
@users = User.where(role: params[:role])
或者,如果目标是在视图页面中显示具有所有这些角色的用户,则可以传递需要过滤掉的角色数组。
@users = User.where(role: ['admin', 'paid_user', 'free_user', 'blocked_user'])
答案 1 :(得分:0)
我该如何优化它?
小问题,范围很广。
首先,不应该使用字符串定义@user.role
。
如果您的字符串错误,或者您希望更改该角色会怎样?您需要将角色分别存储到数据库,允许您引用它们(使用int
)。这可以通过enum
或association
:
#app/models/user.rb
class User < ActiveRecord::Base
enum role: [:admin, :call_user, :buy_user, :blocked_user]
end
通过enum
,您可以访问多个instance
&amp; class
优化查询的方法:
@user = User.find x
@user.admin? #-> true
@user.call_user? #-> false
@user.buy_user? #-> false
@user.blocked_user? #-> false
User.admin #-> collection of admin users
User.call_user #-> collection of call_user users
User.buy_user #-> collection of buy_user users
在你的情况下,它将摆脱where
条款,允许你打电话:
def index
@users = User.all
@admin_users = User.admin
@call_users = User.call_user
@buy_users = User.buy_user
@blocked_users = User.blocked_user
end
<强> ActiveRecord的强>
其次,您没有很多查询;你有很多定义。
我从@Marek Lipka
了解到,当您定义变量时,ActiveRecord
不会查询,只有在视图中输出该变量时才会知道。它被称为"Lazy Loading":
Active Record
查询返回关系是懒惰的。基本上没有理由告诉数据库在最后一刻之前执行查询。如果您根本不需要使用该查询,该怎么办?如果你想在执行它之前让它变得更复杂怎么办?关系为您提供了灵活性,可以更有效地利用数据库的宝贵时间。
这意味着每次定义变量时,ActiveRecord
只会 在需要时点击数据库。
因此, 可以远离您@users
变量的范围:
def index
@users = User.all
end
#app/views/users/index.html.erb
<% roles = %i(admin call_user buy_user blocked_user) %>
<% roles.each do |role| %>
<%= role %>
<%= @users.where(role: role).each do |user| %>
<%= user.name %>
<% end %>
<% end %>
...或者如果您使用的是enum
:
#app/views/users/index.html.erb
<% User.roles.each do |role| %>
<%= role %>
<%= User.send(role).each do |user| %>
<%= user.name %>
<% end %>
<% end %>
<强> DB 强>
如@Sasidaran
所述,实现这一目标的最佳方法是让数据库完成工作。
除了他的代码,你可以做的最好的事情是确保你只是在数据库中找到你要使用的数据。让数据库服务器计算所需的内容,Rails只应用作管道。