急切加载自联接表递归

问题描述 投票:0回答:2

我有一个模特

class MyModel < ActiveRecord::Base
  belongs_to :parent, :class_name => 'MyModel'
  has_many :children, :class_name => 'MyModel', :foreign_key => 'parent_id'
end

而且我想要抓住所有没有父母的物品并将它们与所有孩子一起拿走。换句话说,我想要所有父母及其子女和子女的孩子等等。因此必须以递归方式加载。如果我做

    @result = MyModel.includes(:children)
             .where('parent IS ?', nil)

我只有一个孩子的父母。但我不会生孩子的孩子。有可能递归地获取所有这些吗? albo是否可以计算每个父母的子女数量?

ruby recursion activerecord eager-loading
2个回答
0
投票

我建议你使用像awesome_nested_set这样的嵌套宝石。这将为您提供许多功能,以帮助处理类似对象的集合,并包括存储子计数的工具。


0
投票

您可以通过传入嵌套哈希来递归预加载一定数量的自连接

@result = MyModel.includes(
  children: {
    children: {
      children: {
        children: :children
      }
    }
  }
).where('parent IS ?', nil)

或者更好地动态生成此哈希

这是未经测试的(基本上是伪代码)

scope :recursivly_include_children, -> (max_depth) {
  includes(generate_nested_children_hash(max_depth))
}

def self.generate_nested_children_hash(current_hash = {}, level = 0, remaining_levels)
  if remaining_levels > 0
    // add one level to the current_hash here

    generate_nested_children_hash(current_hash, level+1, remaining_levels-1)
  else
    current_hash
  end
end

然后在控制器中获得最多10个级别的预加载子项:

@result = MyModel.recursivly_include_children(10).where('parent IS ?', nil)
© www.soinside.com 2019 - 2024. All rights reserved.