После того, как вы пояснили, что вам не нужно хранить это дерево в базе данных, я предлагаю выбросить 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"]