嵌套集模型中的热切加载关联

时间:2015-04-01 16:34:30

标签: ruby-on-rails activerecord

我正在使用嵌套集来表示嵌套注释(1个讨论中有很多注释,注释可以回复),我想(如果可能的话)急于加载注释的答案。

此刻我加载所有根节点并迭代它们,如果它们有后代我会渲染它们。但是,如果有很多根节点都有答案,则会触发很多数据库请求。

评论包含以下列: rgt, lft, parent_id

我试图建立这样的关系:

class Comment < ActiveRecord::Base
  has_many :answers, -> (node) { where("lft > ? AND rgt < ?", node.lft, node.rgt) }, class_name: "Comment", foreign_key: :parent_id
end

在Comment实例上调用时,它会获取注释的答案。但是,如果我尝试eager_load它(Discussion.comments.includes(:answers)),它会因为node为零而爆炸。

是否有可能急于加载这样的东西?

1 个答案:

答案 0 :(得分:1)

我想,我找到了解决方案。 如果我看对了,那么您的数据模型如下所示:

Discussion
----------
...

Comment
----------
discussion_id:int
parent_id:int
lft:int
rgt:int

然后AR模型类将是:

class Discussion < ActiveRecord::Base
  has_many :comments
end

class Comment < ActiveRecord::Base
  belongs_to :discussion
end

急切加载讨论(id == 1)及其所有评论和答案树使用:

d = Discussion.includes(:comments).find(1)

这给出了内存中给定讨论的所有注释的集合(d.comments)。

现在我们可以操作此集合来获取任何特定注释的答案,而无需额外的数据库查询。只需将其添加到Discussion类:

def comment_roots
  self.comments.select {|c| c.parent_id.nil? }
end

这到Comment类:

  def answers
    self.discussion.comments.select {|c| c.parent_id = self.id }
  end

  def answers_tree
    self.discussion.comments.select {|c| self.lft < c.lft && c.rgt <   self.rgt }
  end

示例:

d.comment_roots.first.answers