Reputation: 2122
I am using "acts_as_nested_set" in my rails app. (extended with awesome nested set plugin). I was trying to logic out the best way to write a function/method to clone an element and its entire nested set so that each element gets a clone but the relationship structure mimicks the original, just with the new elements.
With nested sets you get parent_id, lft, and rgt
positional columns... instead of just position_id
.
Should I start at the bottom (nodes with no children) of each set and clone up through the parents all the way to a new root?
This seems like either something that has been done or that there would be a method for doing this already for nested sets but I can't see to find anything to guide me.
Thanks
Upvotes: 1
Views: 1983
Reputation: 6790
I did something like this with acts-as-tree. I iterated over the collective set and cloned each item. I saved the source item and the cloned item in a hash where the source was the key and the clone the target. I then used the hash along with the parent references to resolve and remap the relations.
Here's a snippet to help convey the gist.
The clone method simply instantiates a new copy without an id. The descendants method returns a full list of descendants not just immediate ones.
def clone_branch()
h = {self => self.clone} #we start at the root
ordered = self.descendants #preserved order with acts_as_sortable
#clone subitems
ordered.each do |item|
h[item] = item.clone
end
#resolve relations
ordered.each do |item|
cloned = h[item]
item_parent = h[item.parent]
item_parent.children << cloned if item_parent
end
h[self]
end
Upvotes: 2