1

我有一个模型标签,它是一个树模型(使用closure_tree),并且由于 gem,我可以执行以下操作:

Tag.includes(:children).first

急切地加载它的孩子。现在,我有一个实例方法,它也使用孩子。因此,当我通过上述查询获得标签时,遍历标签及其子项并调用此实例方法,bulletgem 抱怨我正在执行 N+1 查询并建议我使用include(children). 出现这种情况是因为我没有加载children的children,所以在调用实例方法的时候,我对一级标签的每个子标签的children进行了单独的查询。

我可以通过执行以下操作来解决此问题:

Tag.includes(children: :children).first

在这种情况下,ActiveRecord 急切地加载标签、它的孩子和它的孩子的孩子。但是,如果只有 3 代,则此方法有效 - 标记是祖父母,然后是父母(它们是根标记的子代)和孙子代(它们是根标记的子代的子代)。如果我有 4 代人,那么我必须这样做:

Tag.includes(children: {children: :children}).first

因此,如果我可以确定depth根标记的最远孙子,有没有办法有条件地构造我的查询 - 如果深度为 2,则使用includes(:children),如果深度为 3 - 使用includes(children: :children)等等?

4

2 回答 2

0

我能想出的最佳解决方案是:

  def included_children(tag_id)
    depth = Tag.find(tag_id).leaves.last.depth
    eval(includes_string(depth))
  end

  def includes_string(depth)
    "{children: #{depth > 1 ? includes_string(depth - 1) : ':children'}}"
  end

我首先找到depth了最深的离开。这告诉我必须调用多少次:children。然后,我根据深度构造一个字符串,并将字符串评估为我在includes方法中使用的代码。欢迎任何改进建议,因为这个解决方案有几个缺陷,我觉得它完全不干净。谢谢你。

于 2014-12-16T09:25:50.677 回答
0

从文档来看:https ://github.com/mceachen/closure_tree#usage你应该使用

Tag.descendants
Tag.self_and_descendants

这将检索所有的孩子、子孩子等。直到它在叶子上结束。

于 2014-12-11T05:48:17.510 回答