0

Along the lines of this question, I'm using deep_cloneable to copy a model with its single association. That association has an attached image (stored in s3), which I want copied at the time of the clone.

This is how I'm doing the deep-clone now - this clones the gallery along with its associated photos, and updates the copied gallery to have a new location_id based on some passed parameters:

new_gallery = @gallery.deep_clone(incude: :photos) do |original, copied_gallery|
  copied_gallery.location_id = gallery_params['Location_id']
end

new_gallery.save

My first thought was to somehow iterate over either the original or copied_gallery photos, to assign photo.image = old_photo.image within the overall deep_clone block, but I don't know if all of the necessary data is accessible/findable at that point.

From there, I wonder if there's access to the (include: :photos) portion of the deep_clone block. Similar to how I have access to both original and copied_gallery, if I could access the original & copied photos within the block, then I could easily assign values. I just don't know if that level of access exists.

If all else fails, I might be better off dropping the (include: :photos) portion of the deep_clone block. I could clone the gallery on its own, then clone the individual photos just after that - something like this:

new_gallery = @gallery.deep_clone do |original, copied_gallery|
  copied_gallery.location_id = gallery_params['Location_id']
end

new_gallery.save

@gallery.photos.each do |photo|
  new_photo = photo.deep_clone do |original, copied_photo|
    copied_photo.image = original.image
  end

  new_photo.save
end

That feels very heavy-handed, though.

Do you have any insight into the (include: :photos) portion of the deep_clone block, or do you have any other ideas on how to set the image for each of the photos being cloned?

Community
  • 1
  • 1
James Chevalier
  • 10,604
  • 5
  • 48
  • 74

1 Answers1

1

I misunderstood the block - all models are being processed in there, not just the one you called deep_clone on.

Take this example:

pirate.deep_clone :include => :parrot do |original, kopy|
  kopy.cloned_from_id = original.id if kopy.respond_to?(:cloned_from_id)
end

kopy refers to both data types, pirate and parrot. That's why you need to include the if kopy.respond_to?(:cloned_from_id) within the block - each model going through it (if you're using include) might not respond to the field you're attempting to work with.

So, in my case, I would do this:

new_gallery = @gallery.deep_clone(incude: :photos) do |original, copied_item|
  copied_item.location_id = gallery_params['Location_id']
  copied_item.image       = original.image if copied_item.respond_to?(:image)
end

new_gallery.save
James Chevalier
  • 10,604
  • 5
  • 48
  • 74