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

How To Attach Polymorphic Associated Records To A Different Model? #124

Closed Petercopter closed 4 years ago

Petercopter commented 4 years ago

Let's say I have a Parrot model, and it's got a polymorphic association with Pirate and Landlubber.

I want to deep clone a Pirate's Parrots and associate them with the Landlubber. I did something similar for a non-polymorphic model, and that worked great (Basically this https://github.com/moiristo/deep_cloneable/issues/109)

So I do

@pirate.deep_clone(include: :parrots, except: [{ parrots: [:parrotable_type] }])

I'm ending up with

[#<Parrot:0x0000559e5add0498 id: nil, name: 'Crackers', parrotable_type: "Pirate", parrotable_id: nil, created_at: nil, updated_at: nil>]

parrotable_type is not cleared, but parrotable_id is cleared.

Is this working as intended?

moiristo commented 4 years ago

When you deep clone an association, it sets the association (pirate parrots) as well as the inverse association (parrot parrotable). I think rails sets the parrotable_type when the duped record is associated. There is no id as the pirate is a new record.

Does it really matter in this case? As you want to associate LandLubber afterwards, I guess you could do the same thing (set the inverse)? Something like:

land_lubber = LandLubber.new
land_lubber.parrots = duped_pirate.parrots.tap { |parrots| parrots.each { |parrot| parrot.parrotable = land_lubber } }
Petercopter commented 4 years ago

@moiristo Thanks, that does make sense. Love that tap, that's some true Rubyist style there 👍