通过关联Rails查询has_many

时间:2013-05-21 02:30:36

标签: ruby-on-rails ruby-on-rails-3 has-many-through

我有一个像这样的has_many协会:

User.rb
has_many :memberships, :dependent => :destroy

has_many :groups, :through => :memberships

Group.rb
has_many :users, :through => :memberships
has_many :microposts


Membership.rb
belongs_to :user
belongs_to :group

首先,我需要知道查询以获取用户的所有组,之后我需要一种方法来显示这些组的所有微博。是否可以使用该信息获得一个查询?

非常感谢!

1 个答案:

答案 0 :(得分:5)

获取用户的群组:

some_user = User.find(some_id)
some_user.groups

要获得微博,你可以这样做:

some_user.groups.each do |group|
  puts group
  puts group.microposts
end

但是,这会导致生成单独的查询以收集每个组的微博。这可以通过使用includes

急切加载微博来解决
some_user.groups.includes(:microposts).each do |group|
  puts group
  puts group.microposts
end

现在只会生成2个查询 - 一个用于获取组,另一个用于获取与这些组关联的所有微博。在幕后,ActiveRecord会将微博与正确的组匹配,并在组中呼叫.microposts时相应地返回它们。

要将所有微博作为哈希值,您可以使用each_with_object来收集它们:

@group_microposts = some_user.groups.includes(:microposts).
                              each_with_object({}){|group, h| h[group] = group.microposts}

这将返回{ group => microposts }形式的哈希值。

要将它们作为数组,可以执行:

@microposts = some_user.groups.includes(:microposts).map(&:microposts).flatten

但是,如果您根本不需要组信息,则可以采用更有效的方法:

@microposts = Micropost.joins(:group => :users).where(:users => {id: some_user.id})

第二种方法更快,因为有两个原因 - 它只需要一个查询(不需要急切加载),db查找效率更高,因为它可以使用可用的索引来执行必要的连接,而不是对文字整数进行过滤列表(随着列表变大,可能会变慢)。