I have a model that is using ActiveStorage:
class Package < ApplicationRecord
has_one_attached :poster_image
end
How do I create a copy of a Package object that contains a duplicate of the initial poster_image file. Something along the lines of:
original = Package.first
copy = original.dup
copy.poster_image.attach = original.poster_image.copy_of_file
Using Active Storage, an application can transform image uploads or generate image representations of non-image uploads like PDFs and videos, and extract metadata from arbitrary files.
Active storage is an inbuilt gem in Rails that developers widely use to handle file uploads. Combined with the encrypted credentials feature in the latest releases of Rails, active storage is a safe and easy method to upload, serve, and analyze files onto cloud-based storage services as well as local storage.
Update your model:
class Package < ApplicationRecord
has_one_attached :poster_image
end
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_image
end
You can duplicate the attachment as such
original = Package.first
copy = original.dup
copy.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 :images
end
original = Post.first
copy = original.dup
original.images.each do |image|
copy.images.attach \
:io => StringIO.new(image.download),
:filename => image.filename,
:content_type => image.content_type
end
It worked for me:
copy.poster_image.attach(original.poster_image.blob)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With