。我有一个方法(如下所示)有很多查询。我该如何优化它?

时间:2016-02-07 07:05:30

标签: ruby-on-rails

我有一个方法(如下所示)有很多查询。我该如何优化呢?

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

2 个答案:

答案 0 :(得分:1)

所有这些都取决于如何定义视图页面,如果在视图页面中用户可以按不同的角色排序,那么它可以写为

@users = User.where(role: params[:role])

或者,如果目标是在视图页面中显示具有所有这些角色的用户,则可以传递需要过滤掉的角色数组。

@users = User.where(role: ['admin', 'paid_user', 'free_user', 'blocked_user'])

答案 1 :(得分:0)

  

我该如何优化它?

小问题,范围很广。

Enum

首先,不应该使用字符串定义@user.role

如果您的字符串错误,或者您希望更改该角色会怎样?您需要将角色分别存储到数据库,允许您引用它们(使用int)。这可以通过enumassociation

来实现
#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只应用作管道。