【发布时间】:2015-07-07 22:58:43
【问题描述】:
我有一个 ActiveRecord,它是 n 叉树的一个节点。模型中有很多类方法可以创建根、追加叶子等等……
由于每次插入都会修改整个树,我希望避免外部类通过 new 和 create 方法来实例化我的模型。
知道怎么做吗? (我在 Rails 4.0.2 中)
更新
所以我使用的树结构的表示是非递归表示 - 按间隔。 The implementation is described there,但它是法语的。
基本上,每个节点都有一个 left_tree 和一个 right_tree 代表一个区间。一个节点的子节点的left_tree和right_tree在父节点的区间内。这种表示允许我在树上进行非常快速的选择,但另一方面有繁重的插入过程。
# Task schema
create_table "tasks", force: true do |t|
t.string "label"
t.integer "tree_level"
t.integer "left_tree"
t.integer "right_tree"
end
然后,为了插入,我需要所有树的区间索引。
# Model Task
# Create the root of the tree. Only static method of the model
def self.create_root! label
Task.create! do |task|
task.tree_level = 1
task.left_tree = 1
task.right_tree = 2
task.label = label
end
end
# Method to add a child for a node. Task model
def create_child! label
new_task = Task.new
Task.transaction do
# Prepare the new task to be inserted in the intervals
new_task.left_tree = right_tree
new_task.right_tree = right_tree + 1
new_task.tree_level = tree_level + 1
new_task.label = label
# create an empty space in the tree
Task.where(
'right_tree >= :right_tree',
{ right_tree: right_tree }).update_all('right_tree = right_tree + 2')
Task.where(
'left_tree >= :right_tree',
{ right_tree: right_tree }).update_all('left_tree = left_tree + 2')
# Save the task, which have now a place in the tree.
new_task.save!
end
reload
return new_task
end
如您所见,模型不应该在我的模型任务之外实例化。 我们应该创建一个根,然后从这个根通过 create_child 方法创建整个树!
【问题讨论】:
-
你能试着解释一下吗? 每次插入都会修改整棵树是什么意思?我们可以看一些代码吗?
-
当然,我想避免发布我丑陋的代码(我通常不是开发 ruby)。我没有发布我所有的代码,但基本上这个想法就在那里。我的数据结构有某种 API,我想避免用户破坏一切。
标签: ruby-on-rails ruby activerecord constructor private