Rails Ancestry对所有节点求和



我正在使用Ancestry宝石。每个节点都有一个与其关联的数值(:value)。每次对一个节点进行CRUD时,我都希望重新计算整个树,以便每个节点最终得到其子节点的值的总和。(叶节点保持不变。)

我的控制器操作包含以下代码以触发重新计算:

def create
  ...
  @tree = Tree.new(tree_params)
  if @tree.save
    Tree.roots.each do |r|
      recalc_tree(r)        
    end
    redirect_to trees_url, notice: "Node was successfully created. " + note.to_s
  else
    render :new, notice: "There was an error saving this node. Please try again."
end

在控制器底部的私人部分,我有一个自定义的助手方法:

def recalc_tree(r)
    total = 0
    if r.has_children?
        r.children.each do |c|
            total = total + recalc_tree(c)
        end
        r.value = total
    else
        r.value
    end
end

我在浏览器中没有收到任何错误(节点保存正确),但这也不会更新祖先节点的任何值。

我试着在控制台中运行助手,但出现了一个"未定义的方法"错误:

>> helper.recalc_tree(Tree.roots.first)
Tree Load (0.0ms)  SELECT  "trees".* FROM "trees"  WHERE "trees"."ancestry" IS NULL  ORDER BY "trees"."id" ASC LIMIT 1
NoMethodError: undefined method `recalc_tree' for #<ActionView::Base:0x5fc82c0>

我做错了什么?

实现这一点的更多rails风格的方法是使用ActiveRecord的回调(http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html)。此外,由于当更新节点时,只有更新节点的祖先需要更新,因此我们可以通过只更新根路径上的祖先来节省一些CPU周期。

示例:

class Tree < ActiveRecord::Base
  after_save :update_ancestors
  ...
  ...
  private
  def update_ancestors
    self.ancestors.each do |ancestor|
      ancestor.value = ancestor.descendants.pluck(:value).sum
      ancestor.save
    end
  end
end

我实际上并没有在我的机器上运行这个代码,但这几乎是这个问题的方向!

相关内容

  • 没有找到相关文章

最新更新