获得ActiveRecord :: Relation关联的理想方式

时间:2015-09-18 20:41:42

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

请考虑以下事项:

class User < ActiveRecord::Base
  has_many :posts
end

现在我想为一些被禁用的用户发帖子。

User.where(is_banned: true).posts

这会产生NoMethodError,因为帖子未在ActiveRecord::Relation上定义。

使上面的代码工作的最简单的方法是什么?

我能想到

User.where(is_banned: true).map(&:posts).flatten.uniq

但这效率很低。

我也可以想到

user_scope = User.where(is_banned: true)
Post.where(user: user_scope)

这需要在Post模型中设置用户关联,并且它似乎生成嵌套选择。我不知道效率。

理想情况下,我想要一种允许遍历多个关系的技术,所以我可以编写如下内容:

User.where(is_banned: true).posts.comments.votes.voters

这应该给我每个选民(用户)投票赞成被禁用户写的帖子。

2 个答案:

答案 0 :(得分:2)

为什么不使用joins

Post.joins(:user).where(users: {is_banned: true})

这将生成SQL

的效果
SELECT * 
FROM posts
INNER JOIN users ON posts.user_id = users.id
WHERE users.is_banned = true

这似乎正是您所寻找的。就你的长链而言,你可以通过更深入的连接来做同样的事情。

答案 1 :(得分:1)

在您的代码中:

User.where(is_banned: true)

将是和ActiveRecord :: Relation,你需要一条记录。这样做,如果从用户模型会更复杂。根据关系的设置方式,您可以在Post模型中添加范围。

scope :banned_users, -> { joins(:users).where('is_banned = ?', true) }

然后,您只需致电Post.banned_users即可获取被禁用户创建的所有帖子。