Rails 5,重构,针对多个条件的最佳查询

时间:2016-06-17 20:29:11

标签: sql ruby-on-rails ruby rails-activerecord ruby-on-rails-5

我有一个我最近更新到Rails 5的rails应用程序。我有一个看起来像这样的数据模型(简化):Users可以有很多AppsUsers也可以是多个Member的{​​{1}},每个Team也可以有多个Team。在我的App索引视图/控制器中,我想列出他/她创建的所有用户应用,我还要列出属于App的所有应用Team }是Users

我觉得有一种比我目前的实现更好,更高效的方法(可能是Rails 5中的新功能)。这就是我目前的实现方式:

Member

那么,是否有更清洁,更优化的方式来做我正在做的事情?那看起来怎么样?

修改

这就是我的活跃模型关联的样子:

apps = []
# First get all the team apps where the user is a member, but haven't created the app. 
current_or_guest_user.teams.each do |team|
  team.apps.each do |app|
    unless app.user.eql?(current_or_guest_user)
      apps << app
    end
  end
end
# ... then get all the apps that the user have created. 
current_or_guest_user.apps.each do |app|
  unless apps.include?(app)
    apps << app
  end
end
# Return the apps. 
@apps = apps

修改2

我想知道Rails 5方法# App.rb belongs_to :user belongs_to :team # User.rb has_many :apps, dependent: :destroy has_many :teams has_many :teams, through: :members # Team.rb has_many :apps, dependent: :destroy https://github.com/rails/rails/pull/16052)是否可用于此用例,例如:

#or

1 个答案:

答案 0 :(得分:3)

我认为以下代码应该更简洁地完成此任务:

# using a shorter variable name
user = current_or_guest_user

# does the same thing as your first loop over teams
set1 = user.teams.includes(:apps).where("apps.user_id = ?", user.id).map(&:apps)

# does the same thing as the second loop
# (no need to check for duplicates here)
set2 = user.apps

# combine the two queries without adding duplicates
return set1 | set2

道歉,如果这不是开箱即用,我还没有测试过。

这里有几个概念:

  • includes将通过关联“预加载”记录。这通过单个查询获取所有关联记录,而不是触发单个SQL查询以获取每个查询。
  • where("apps.user_id = ?", user.id)根据关联记录的user_id过滤查询。这里的?是一个由user.id取代的变量。