moiristo / deep_cloneable

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

Missing relations in new (cloned) model #70

Closed emiellohr closed 7 years ago

emiellohr commented 8 years ago

Im cloning an event object with nested models like show here:

    copied_object = self.deep_clone include: [
      :alternative_tickettexts,
      :conversion_script,
      :event_email_description,
      :memberships,
      :performances,
      :sponsor_images,
      passe_partouts: [:performances, {categories: :products}],
      categories: :products,
      ], use_dictionary: true, validate: false

The result is a cloned object, but misses the categories: :products on the copy. The use of use_dictionary doesn't seem to make a difference. I tried various alternatives, but never ended up with the required result. Can you give me some advice here?

moiristo commented 8 years ago

What kind of association are we talking about? Did it clone the categories? Are the products still missing after saving the copy?

joshleitzel commented 7 years ago

I've come across this issue as well, and it seems to be due to the use of a multi-item hash inside the include array. The deep_clone method appears to accept these formats:

record.deep_clone(include: { relation1: :attr1, relation2: :attr2 })
record.deep_clone(include: [:relation3, { relation1: :attr1 }, { relation2: :attr2 }])

but does not support using a single hash inside the array if it has multiple keys:

record.deep_clone(include: [:relation3, { relation1: :attr1, relation2: :attr2 }])
record.deep_clone(include: [:relation3, relation1: :attr1, relation2: :attr2])

I agree this is a tad confusing/unexpected since the last format would be the more idiomatic way to write this in Rails these days. I toyed around for a bit with the code but couldn't find a way to make this work without breaking some of the other use cases, but here's a test to show the problem:


def test_multiple_and_deep_include_association_with_array
  deep_clone = @jack.deep_clone(include: [:parrot, treasures: :gold_pieces, mateys: {}])
  assert deep_clone.new_record?
  assert deep_clone.save
  assert_equal 1, deep_clone.treasures.size
  assert_equal 1, deep_clone.gold_pieces.size
  assert_equal 1, deep_clone.mateys.size
end

For now, the second format I showed above (with explicitly separate hashes) can be used if you want to mix array and hash relations.

PS: Thank you for this wonderful gem. It's helped me greatly optimize a tedious workflow in one of my projects. :)

moiristo commented 7 years ago

Thanks! I'll check it out soon, should be fixable I think..

moiristo commented 7 years ago

I fixed the test now in 517537db5edc472026bea772c529fb0ee91b8978 by 'normalizing' the includes list (converting multikey hashes to singular hashes). Should be ok I think?