急切加载自联接表递归

时间:2017-12-09 20:06:06

标签: ruby recursion activerecord eager-loading

我有一个模特

class SteeringWheel {
        public: float rotation;
        public: SteeringWheel(void) {
                this->rotation = 0.f;
        }
};

class Car {
        private: SteeringWheel *steeringWheel;
        public:

        /**
         * @param[?] steeringWheel Is the steering wheel in or in/out? 
         */
        Car (SteeringWheel *steeringWheel) {
                this->steeringWheel = steeringWheel;
        }

        /**
         * @param[in] degree Steering amount in degrees.
         */
        void steer(float degree) 
        {
                this->steeringWheel->rotation += degree;
        }
};

int main(int argc, char **argv)
{
        SteeringWheel steeringWheel();

        /* car() uses steeringWheel as read only. */
        Car car(&steeringWheel);

        /* steer() uses steeringWheel from car() to write. */
        car.steer(50.f);

        return 0;
}

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

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

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

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分: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)