How do I duplicate a file stored in ActiveStorage in Rails 5.2 How do I duplicate a file stored in ActiveStorage in Rails 5.2 ruby-on-rails ruby-on-rails

How do I duplicate a file stored in ActiveStorage in Rails 5.2


Update your model:

class Package < ApplicationRecord  has_one_attached :poster_imageend

Attach the source package’s poster image blob to the destination package:

source_package.dup.tap do |destination_package|  destination_package.poster_image.attach(source_package.poster_image.blob)end


If you want a full copy of the file so that both the original record and the cloned record have their own copy of the attached file, do this:

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

ActiveStorage::Downloader.new(original.poster_image).download_blob_to_tempfile do |tempfile|  copy.poster_image.attach({    io: tempfile,     filename: original.poster_image.blob.filename,     content_type: original.poster_image.blob.content_type   })end

After Rails 5.2 (whenever a release includes this commit), then you can just do this:

original.poster_image.blob.open do |tempfile|  copy.poster_image.attach({    io: tempfile,     filename: original.poster_image.blob.filename,     content_type: original.poster_image.blob.content_type   })end

Thanks, George, for your original answer and for your Rails contributions. :)


Found the answer by looking through Rails's tests, specifically in the blob model test

So for this case

class Package < ApplicationRecord  has_one_attached :poster_imageend

You can duplicate the attachment as such

original = Package.firstcopy = original.dupcopy.poster_image.attach \  :io           => StringIO.new(original.poster_image.download),  :filename     => original.poster_image.filename,  :content_type => original.poster_image.content_type

The same approach works with has_many_attachments

class Post < ApplicationRecord  has_many_attached :imagesendoriginal = Post.firstcopy = original.duporiginal.images.each do |image|  copy.images.attach \    :io           => StringIO.new(image.download),    :filename     => image.filename,    :content_type => image.content_typeend