Reputation: 563
My json:
{
"catalogs": {
"name": "catalog 1C",
"children": [{
"name": "Philips",
"children": {}
},
{
"name": "BenQ",
"children": [{
"name": "Monitor",
"children": [{
"name": "19 inches",
"children": [{"name": "IPS", "children": {}},
{"name": "TFT","children": {}}]
},
{
"name": "24 inches",
"children": {} }]
}]
}
]
}
}
Json have same keys and levels of nesting within each other.
сhildren can have many directories (for example IPS, TFT).
This is a menu where some items should be on the same level. I use gem ancestry
I wrote a recursive function (in the controller):
def call
# file - inside the json to parse
data_hash = JSON.parse(file)
data_hash["catalogs"]["children"].each do |k|
ancestry = Category.create_with(name: k["name"]).find_or_create_by!(uid_catalog: k["uid_catalog"])
if k["children"].present?
k["children"].each do |parent|
parent["children"].each do |child|
walk_tree(child, ancestry)
end
end
end
end
end
def walk_tree(root, ancestry)
ancestry = ancestry.children.find_or_create_by!(name: root["name"])
root["children"].each do |child|
ancestry = ancestry.children.find_or_create_by!(name: child["name"])
walk_tree(child["children"], ancestry) if child["children"].present?
end
end
Currently the function outputs:
- BenQ
- 19 inches
- IPS
- TFT
I want to have it like this (missing one level Monitor
):
- BenQ
- Monitor
- 19 inches
- IPS
- TFT
- 24 inches
Upvotes: 0
Views: 428
Reputation: 2791
The cause of the problem reveals after quick debugging. Take a look at this chunk of code. Please note my comments:
data_hash["catalogs"]["children"].each do |k|
# k == { "name": "BenQ", "children": [...] }
ancestry = Category.create_with(name: k["name"]).
find_or_create_by!(uid_catalog: k["uid_catalog"])
if k["children"].present?
k["children"].each do |parent|
# parent == { "name": "Monitor", "children": [...] }
parent["children"].each do |child|
# child == { "name": "19 inches", "children": [...] }
walk_tree(child, ancestry)
end
end
end
end
So you do not process parent
as a separate node; instead your code immediately dives deeper into parent["children"]
. That's why one level of nesting is missing.
I think you need to remove inner iterator, and rewrite it as:
data_hash["catalogs"]["children"].each do |k|
ancestry = Category.create_with(name: k["name"]).
find_or_create_by!(uid_catalog: k["uid_catalog"])
if k["children"].present?
k["children"].each do |child|
walk_tree(child, ancestry)
end
end
end
Upvotes: 1