在您澄清不需要将此树存储在数据库中之后,我建议丢弃 NestedSets(它们用于在 RDBMS 上存储嵌套的对象集,您不需要)。你需要什么我简单的树
class Node
attr_accessor :parent, :children, :text
def initialize(text)
@text = text
@children = []
end
end
由于我有权选择 CSV 文件的格式,所以我建议这样:
id,parent,text
1,,"1"
2,1,"1.1"
3,1,"1.2"
3,2,"1.1.1"
树根是第一行,没有父级,并且总是有父级在其子级之前声明的顺序。这样你就可以建树了
def build_tree(rows)
nodes = {}
rows.each do |row|
node = Node.new(row[:text])
nodes[row[:id]] = node
node.parent = nodes[row[:parent]]
nodes[row[:parent]].children << node if row[:parent]
end
nodes.values.find {|node| node.parent.nil? }
end
root = build_tree(rows)
root.text #=> "1"
root.children.map(&:text) #=> ["1.1", "1.2"]
root.children[0].children.map(&:text) #=> ["1.1.1"]
如果你需要从子节点中获取所有文本,那么你需要使用更多的技巧
def get_nodes(tree_node)
[ tree_node, tree_node.children.map{|node| get_nodes(node)} ].flatten
end
get_nodes(root).map(&:text) #=> ["1", "1.1", "1.1.1", "1.2"]