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