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

ActiveStorage support #90

Closed Artur-Sulej closed 6 years ago

Artur-Sulej commented 6 years ago

This is a really great gem - thanks for sharing it. I'm currently using newest version of Rails, which offers ActiveStorage for attaching files. Is there any recommended way to clone record with deep_cloneable along with its file(s) (has_one_attached or has_many_attached)? That would also involve duplicating the files (on a hosting service like GCP).

moiristo commented 6 years ago

Hi,

I haven't used ActiveStorage yet, so I don't know actually. Maybe you could do something similar as the proposed solution for Carrierwave? (https://github.com/moiristo/deep_cloneable#cloning-models-with-files-associated-through-carrierwave). Could you share the solution when you find one, then I'll add it to the readme.

bettysteger commented 6 years ago

here is a solution:

In Rails 5.2, grab this code and put it in config/initializers/active_storage.rb, then use this code to do a copy:

pirate.deep_clone include: :parrot do |original, kopy|

  if kopy.is_a?(Pirate) && original.avatar.attached?
    ActiveStorage::Downloader.new(original.avatar).download_blob_to_tempfile do |tempfile|
      kopy.avatar.attach({
        io: tempfile,
        filename: original.avatar.blob.filename,
        content_type: original.avatar.blob.content_type
      })
    end
  end

end

source: https://stackoverflow.com/questions/49631530/how-do-i-duplicate-a-file-stored-in-activestorage-in-rails-5-2

moiristo commented 6 years ago

Thanks for the info, I'll add a section to the readme for it!

bettysteger commented 6 years ago

basically there are 2 options, just link to the attached one or really copy it, see https://stackoverflow.com/questions/49631530/how-do-i-duplicate-a-file-stored-in-activestorage-in-rails-5-2

martijnbolhuis commented 5 years ago

Actually, there is an easier way. Activestorage just uses regular activerecord associations which can be copied by deep_cloneable using the include option.

For example:

class User < ActiveRecord::Base
  has_one_attached :avatar
end
user = User.create(avatar: File.read(...))
user.deep_clone(:include => [:avatar_attachment, :avatar_blob])

Note that this requires the latest changes from the master branch of this gem which add support for has_one associations. These changes haven't been released yet in current version (2.3.2).

moiristo commented 5 years ago

@martijnbolhuis does this always work, or only for certain kinds of storage services? Will this yield a shallow copy or a full copy?