Hi everyone,
I need to add functionality to my Phoenix App for my users to be able to completely duplicate a given struct and all its associations.
I am thinking of using Ecto.Multi so that I can ensure the duplication process completed successfully.
The problem at the moment is that my struct has deeply nested associations and I can’t seem to be able to figure out a way to duplicate my root struct and all the related associations with the new ID’s that are generated after via the Multi.
Let’s say I have a %City{}
that has many %Neighborhood{}
which have many %House{}
which have many %GroupOfIndividuals{}
which have many %Individual{}
.
My goal is to essentially “clone” a %City{}
and have the new city (the clone) have its one ID and obviously new ID’s all the way down to the individuals, if that makes sense.
I am not sure I see the difficulty? Use Repo.transaction
and just start top to bottom, doing put_assoc
of the lower-level objects pointing at the higher-level objects (after they are inserted).
Or you can just create all objects in memory as structs (not changesets) and do a Repo.insert
on that.
If your associations make a tree, then this is relatively easy. If there are cycles in your associations, this is less easy. If it’s a nice tree then you can:
city = Repo.preload(city, [various: [associations: [go: :here]])
Then, recursively descend through the struct tree and strip out all of the id
values, and parent foreign key column values:
dup_city = strip_ids(city)
Then you can just Repo.insert(dup_city)
and Ecto will handle inserting the whole tree.
Thank you very much.
How should I best recursively descend through the struct?
Also, I am using Ecto.Multi and this is the first time I hear Repo.insert(dup_city)
mentioned in that context.
Did you by chance mean Repo.transaction()
?
Thank you, at the moment I was manually inputing the parent element id, have never used put_assoc but I will try it.