moiristo / deep_cloneable

This gem gives every ActiveRecord::Base object the possibility to do a deep clone that includes user specified associations.
MIT License
785 stars 89 forks source link

deep_clone not called on has_many_through relation #121

Closed abaird closed 1 year ago

abaird commented 4 years ago

I have a deeply nested datamodel that at some point has a has_many_through relation with additional datastructures beneath it that need to be copied. This would normally happen in the process_joined_object_for_deep_clone method. However, even when I enable the dictionary, the call to find_in_dictionary_or_dup is passed a false value for dup_on_miss which causes the deep_clone method to not get called, truncating the copy of part of my datastructure I'm attempting to copy. It's unclear to me why find_in_dictionary_or_dup is passed a false value here. I see that all of the different relations are passed the same argument list but for some reason it's not working correctly when trying to use a has_many_through relation.

I will post more details shortly, but I need to establish this issue so I can get a placeholder to refer to it internally.

moiristo commented 4 years ago

Hi, thanks for your question. I think there has always been some discussion regarding 'through' relationships and what they mean. You could say that everything needs to be duped, but you could also justify that the new copy should just have a new link to the original object. The latter is what's happening now. It was introduced in #47.

If you really want to create copies instead, would it be a possibility for you to dup via the original relationship instead? For example:

has_many :order_items 
has_many :extras, through: :order_items

# Don't do this
order.deep_clone(include: :extras)
# Do this instead
order.deep_clone(include: { order_items: :extra })
pamatya1 commented 3 years ago

Hi Moiristo, firstly thank you for creating this gem. I have question related to above has_many through relationship. I really need to copy of the original relationship, and i tried your suggestion it somehow doesn't make sense to me. Here is my has many through relation

class Parent < ApplicationRecord
  has_many :child, dependent: :destroy
  has_many :grand_child, through: :child

I need to create a copy of Parent along with copy of child with new parent with same grand child, Is this possible to do? i.e. child table should contain

parent_id, grand_child_id, created_at, updated_at -> Original 
new_parent_id, grand_child_id, created_at, updated_at. -> copy 

Thanking you in advance.

moiristo commented 3 years ago

Hi,

If you only include the child (parent.deep_clone(include: :child)), I think the grand_child_id should remain the same for the copy of the child? Is that what you want? The example is a bit strange, because you specify a has_many with a singular name (hm :child instead of hm :children), so I'm not sure if I'm understanding everything correctly :)

MattBudz commented 1 year ago

This helped out a ton order.deep_clone(order_items: :extra)

although, it should be order.deep_clone(order_items: :extras)

Thanks a lot for this gem!