I am trying to seed multiple image attachments to a model. I have been using this link but I am still sort of stuck since what I aim to do differs a little since:
I am trying to attach multiple images to each object (which I seed) in the model
I want to retrieve these images from my S3 bucket and attach them to the objects (is this possible?)
Here's my seed.rb:
shirt = Item.create(name:"Basic Shirt",price:19.99)
skirt = Item.create(name:"Basic Skirt",price:29.99)
sweater = Item.create(name:"Basic Sweater",price:39.99)
kid_hood = Item.create(name:"Basic Kid Hoodie",price:19.99)
# somehow attach images here?
I am using the aws-sdk-s3 gem in order to connect Active Storage to my S3 bucket. Please tell me if any additional files are needed for viewing. I will happily edit this post to include it.
ActiveStorage work on plain byte streams, so you can download the file (using open-uri for instance) and assign the stream as the content of the attachment.
Assuming you have the following (adapt if different)
class Item < ApplicationRecord
has_one_attached :photo
end
you can have your seeds as:
require 'open-uri'
shirt = Item.create(name:"Basic Shirt",price:19.99)
shirt.photo.attach(io: open('your-s3-nonexpiring-url'), filename: 'foo.bar')
# ...
Just a note: as of Ruby 3.0, you will need to call URI.open instead of open. See the reference to open-uri here.
Related
A user uploads a document and this gets stored in Azure with ActiveStorage. The next step is that the backend processes this and therefore I have a service object to do this. So I need to download the file from Azure to the tmp folder within the Rails app. How do I download the file? I cannot use rails_blob_url because it is not available in a service object, only in controllers and views.
When I still used Paperclip I did something like this:
require 'open-uri'
file = Rails.root.join('tmp', user.attachment_file_name)
name = user.attachment_file_name
download = open(user.attachment.url)
download_result = IO.copy_stream(download, file)
How can I do something similar with ActiveStorage?
You can use ActiveStorage::Blob#open:
Downloads the blob to a tempfile on disk. Yields the tempfile.
Given this example from the guides:
class User < ApplicationRecord
has_one_attached :avatar
end
You can do this with:
user.avatar.open do |tempfile|
# do something with the file
end
If its has_many_attached you of course need to loop through the attachments.
See:
Active Storage Overview
In my Rails app I have a module that takes several images, and using RMagick "stitches" them together into a new single image. I'm able to successfully create the final image, but I'm having trouble saving this new image as an attachment to a model (using CarrierWave). The method that does the stitching looks like this:
def generate_collage(params)
final_image = ImageList.new
# ... code that puts together the composite image ...
return final_image.append(true).to_blob { |attrs| attrs.format = 'JPEG' }
end
I've got my User model with an uploader mounted:
class User < ActiveRecord::Base
mount_uploader :image, UserImageUploader
end
In the CarrierWave documentation under the ActiveRecord section, they show how to assign a new image, but they assume the file already exists somewhere. In my case it doesn't yet exist on the filesystem, and I'm outputting a blob... is there any way to go from that blob to generating an image upload for CarrierWave?
I suppose I'm trying to avoid saving this image temporarily into "#{Rails.root}/tmp/" and then reading it from there... it seems like I could cut out this step and send directly to CarrierWave somehow, but I don't know how! Is it possible?
I'm working on something similar right now. This should be possible, but an easy workaround is to save it to a temp file:
temp_file = Tempfile.new([ 'temp', '.png' ])
image.write(temp_file.path)
user = User.new
user.avatar = temp_file
user.save
temp_file.close
temp_file.unlink
I'm hoping to try to improve it to remove the file system dependency completely, by following the advice in one of these answers: How to handle a file_as_string (generated by Prawn) so that it is accepted by Carrierwave?
In my rails project, I need the user to upload a file (input_file) which I will process using an external application. Once, it is completed, I want to attach the processed file to the same model as a different attachment (output file).
I have been able to create a form and use paperclip to allow the user to upload the input_file to my model FileProcessor. Im not sure on the next step as to how do I call an executable on the input_file and save it as output_file.
Based on paperclip, once the file is upload, I can access the path via input_file.path
output_file = %w{external_app input_file.path out_file_name}
Class FileProcessor
has_attached_file :input_file
has_attached_file :output_file
Im confused as to where this call to run the external app be placed? in the model or in the controller (def create). Also, how do I work with paperclip to associate the output_file with the model without actually uploading.
The location for such code depends on what kind of business your external process does. With the requirements as depicted in the question, it would be as simple as this:
class FileProcessor < ActiveRecord
...
after_validation do |fp|
tmp_file = "/tmp/#{rand}"
system "/usr/bin/awesome.sh #{fp.input_file.path} > #{tmp_file}"
fp.output_file = File.open(tmp_file)
end
...
end
I hope, this is what you are looking for.
I have video model with the following definition:
class Video
require 'carrierwave/orm/activerecord'
mount_uploader :attachment, VideoUploader
mount_uploader :attachment_thumbnail, VideoThumbnailUploader
...
end
When I upload a video file. It also sends the file to our encoding service Zencoder, which encodes the video file and creates a thumbnail for it.
Normally, I could do something like #video.attachment.url, which will return the path of the video file. I'd like to do the same thing with the thumbnail. i.e. #video.attachment_thumbnail.url
However, since the attachment is created by our encoding service, which also uploads it to a specified S3 bucket. How do I assign the attachment to the attachment_thumbnail column for the record?
Can I simply do something like:
#video.update_attributes(
:attachment_thumbnail => 'https://bucket_name.s3.amazonaws.com/uploads/users/1/video/1/thumb.png'
)
Is it possible to assign files like this to Carrierwave?
You can do the following:
#video.remote_attachment_thumbnail_url = 'https://bucket_name.s3.amazonaws.com/uploads/users/1/video/1/thumb.png'
But that will cause Carrierwave to download + reprocess the file rather than just make it the thumbnail. If you're not going to use Carrierwave's processing, then it might make more sense to just store the URL to the thumbnail on the model rather than even using Carrierwave.
This worked for me, with CarrierWave 0.5.8
model.update_attributes(:remote_uploader_url => "http://path/to/image.jpg")
Of course, you need to set remote_uploader_url to be attr_accessible for this.
I was looking for this as well.
The blocking point in the zencoder case would be that Carrierwave doesn't track different different file type versions for the original file. It only references the original file.
So having the original file as an .mp4 a a thumbnail version as a .png doesn't work.
While you can have an 'image.png' and also track 'thumb_png_image.png', you can't also create a 'thumb_jpg_image.jpg' for the same file.
Otherwise you could create a dummy version and using conditional versioning tell CW not to process it.
Since CW would create the dummy version anyway but not upload it, you could have it reference a path matching the file returned by Zencoder. But oh well...
At the end of this episode (7:35), Ryan Bates adds a remote_image_url in a file form upload:
http://railscasts.com/episodes/253-carrierwave-file-uploads
I tried storing a local image in a rails console.
Because I have many pictures in my local storage (I use crawler to download tons of pictures), I want to store them into a database, with the benefit of paperclip to do some image job, like thumbnail etc.
If I use a webpage to save new pictures to database one by one, it will cost a lot of time. So I want to find a way in rails console (some code) that can batch save-picture-into-database.
To further clarify #andrea's answer:
YourPaperclippedModelHere.new(:your_paperclip_field => File.new(path, "r"))
So if your model is called Image and your paperclip field is data:
Image.new(:data => File.new(path_to_your_file, "r"))
If this is the model:
class User < ActiveRecord::Base
has_attached_file :avatar
end
then the following should work from the console:
>> User.create(:avatar => File.open('/path/to/image.jpg', 'rb'))
I dont know if it is what you want ... but
to save an paperclip asset from console
You could simple use a File instance .
a.e.
Image.new :data=>File.new("/path/to/image.jpg","r")
Late Answer but hopefully it will work for others.
You need to include.
File.new("#{Rails.root}/public/images/default_avatar.png", "r")