我正在使用the Ancestry gem。每个节点都有一个与之关联的数值(: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>
我做错了什么?
答案 0 :(得分:1)
更多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
我实际上没有在我的机器上运行此代码,但这几乎是这个问题的方向!