Ruby on rails Rails中的嵌套ActiveRecord关系

Ruby on rails Rails中的嵌套ActiveRecord关系,ruby-on-rails,ruby,activerecord,relationship,Ruby On Rails,Ruby,Activerecord,Relationship,我有很多模型 class User < ActiveRecord::Base belongs_to :group end class Group < ActiveRecord::Base has_many :users has_many :posts end class Post < ActiveRecord::Base belongs_to :group has_many :comments end class Comment < Active

我有很多模型

class User < ActiveRecord::Base
  belongs_to :group
end

class Group < ActiveRecord::Base
  has_many :users
  has_many :posts
end

class Post < ActiveRecord::Base
  belongs_to :group
  has_many :comments
end

class Comment < ActiveRecord::Base
  belongs_to :post
end
class用户
要获取用户的帖子,我可以执行
user.find(1).group.posts.all
,但如果我想要用户帖子的所有评论,我不能执行
user.find(1).group.posts.all.comments.all


除了循环浏览所有帖子外,是否有一个简单的解决方案可以获取用户帖子的所有评论?

您想要的是“有很多通过”关系:

将以下内容添加到您的组类中

has_many :comments, through: :posts
然后,您可以通过以下方式获得评论:

User.find(1).group.comments

仅仅通过::posts添加一个
有很多:注释是不够的。
然后,类似于
User.find(1).group.comments的查询将为用户的组提供所有注释,而不是指定的用户

另一种方法是查找给定用户的所有帖子ID,并使用该ID查找该用户帖子的评论:

post_ids = User.find(1).group.posts.map(&:id).uniq
user_comments = Comment.where(:post => post_ids)
单一查询解决方案:

Comment.joins(post: {group: :users}).where(users: {id: 1})
结果查询:

SELECT "comments".* FROM "comments"
  INNER JOIN "posts" ON "posts"."id" = "comments"."post_id"
  INNER JOIN "groups" ON "groups"."id" = "posts"."group_id"
  INNER JOIN "users" ON "users"."group_id" = "groups"."id"
  WHERE "users"."id" = 1

这将为每个帖子触发一个查询,这是非常低效的。它被称为N+1查询,请参见否,它实际上会导致3个sql查询。一个用于选择用户。然后按如下方式选择基于用户组的帖子:select posts.*from posts,其中posts.group_id=1。第三个选项使用如下查询来选择注释:SELECT comments.*from comments where comments.post_id IN[1,2,3,4,5]您是对的,对不起。但是,这仍然会执行得很糟糕,因为您必须将值从数据库读取到Ruby,只需将它们重新放入以选择注释,而不是进行连接。由于用户和注释之间没有直接关系,因此用户组的注释在语义上与用户的注释等效。此外,还有4个而不是3个查询(每个模型一个),我认为应该是
where(:post_id=>post_id)
而不是
where(:post=>post\u id)
这将为用户组提供所有注释,而不是为属于指定用户的帖子提供注释。这一点很好,但基于OP获取帖子的方式(user.find(1).group.posts),我假设这是所需的行为。如果不是的话,数据库结构需要改变。OP说:“获取用户帖子的所有评论”,所以这就是我的假设。数据库结构很好,诀窍是提出一个有效的查询。只要所需的关系是Post和Group之间的关系,而不是Post和User之间的关系,数据库结构就很好。如果您需要知道帖子(和/或其评论)属于哪个用户,那么数据库将需要posts表中的User_id字段(对于帖子),或者如果只需要comments need,则需要comments表中的User_id字段。这将改变数据库结构和获取信息的方式。根据Sævar对我下面答案的评论,我认为最好指出该用户。find(1)。group.posts检索该用户组中的所有帖子,而不仅仅是该用户发表的帖子。这就是你想要的吗?