请考虑以下事项:
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
这应该给我每个选民(用户)投票赞成被禁用户写的帖子。
答案 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
即可获取被禁用户创建的所有帖子。