Сначала возьмите свое дерево, преобразуйте его в список путей к листьям, аналогично:
def leaves_paths tree
if tree[:children]
tree[:children].inject([]){|acc, c|
leaves_paths(c).each{|p|
acc += [[tree[:name]] + p]
}
acc
}
else
[[tree[:name]]]
end
end
(Не уверен, что выше точно соответствует вашей структуре jsTree, но принцип тот же.)
Вот пример ввода и вывода:
tree = {name: 'foo', children: [
{name: 'bar'},
{name: 'baz', children: [
{name: 'boo'},
{name: 'zoo', children: [
{name: 'goo'}
]}
]}
]}
p leaves_paths tree
#=> [["foo", "bar"], ["foo", "baz", "boo"], ["foo", "baz", "zoo", "goo"]]
Затем для каждого пути вызовите FileUtils#mkdir_p
:
paths = leaves_paths tree
paths.each do |path|
FileUtils.mkdir_p(File.join(*path))
end
И с тобой должно быть все в порядке.
Редактировать: Более простая версия:
Вам не нужно создавать список листьев, достаточно пройти по всему дереву и создать каталог для каждого узла:
# executes block on each tree node, recursively, passing the path to the block as argument
def traverse_with_path tree, path = [], &block
path += [tree[:name]]
yield path
tree[:children].each{|c| traverse_with_path c, path, &block} if tree[:children]
end
traverse_with_path tree do |path|
FileUtils.mkdir(File.join(*path))
end
Edit2:
Ой, прости, я неправильно понял. Итак, вот способ создать хэш на основе дерева каталогов на диске:
Dir.glob('**/*'). # get all files below current dir
select{|f|
File.directory?(f) # only directories we need
}.map{|path|
path.split '/' # split to parts
}.inject({}){|acc, path| # start with empty hash
path.inject(acc) do |acc2,dir| # for each path part, create a child of current node
acc2[dir] ||= {} # and pass it as new current node
end
acc
}
Итак, для следующей структуры:
#$ mkdir -p foo/bar
#$ mkdir -p baz/boo/bee
#$ mkdir -p baz/goo
Код выше возвращает этот хеш:
{
"baz"=>{
"boo"=>{
"bee"=>{}},
"goo"=>{}},
"foo"=>{
"bar"=>{}}}
Надеюсь, вам удастся удовлетворить это вашим потребностям.