In model I have something like
has_attached_file :logo, something_here
Code/ Uploading logo is working fine, but I need dimensions before uploading the logo.
So when I am using geometry, error is thrown for
undefined local variable or method 'logo' for #<Class:0xbfabbc0>
Any idea how to solve this? Or is there any other way to get the dimension before storing the data.
You can hook to after_image_post_process. Here is working code from one of my projects:
class Photo < ActiveRecord::Base
has_attached_file :image
after_image_post_process :save_thumb_file_size
def save_thumb_file_size
self.thumb_file_size = self.image.queued_for_write[:thumb].size if self.image.queued_for_write.key?(:thumb)
return true
end
end
Did you generate a migrations related to this field?
rails generate paperclip photo logo
and run rake db:migrate?
Related
In my Rails 5 app I am using Carrierwave to upload images.
I have to model that uses the same uploader:
account.rb:
mount_uploader :logo, ImageUploader
image.rb:
mount_uploader :image, ImageUploader
This uploads the file to:
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
The strange this now is that I can use:
#account.logo&.url(:thumb) // works!
#account.logo&.image_url(:thumb) // error!
But on the image model (one product has many images):
#product.images.first&.image_url(:thumb) // works!
#product.images.first&.url(:thumb) // error!
So in the first case I have to use .url and in the second one .image_url
An I have no idea why...any help?
The instance method image_url is defined dynamically based on the column that is passed to mount_uploader and simply calls url on the column. The definition looks like this...
def #{column}_url(*args)
#{column}.url(*args)
end
So, I would suspect that logo_url would work on #account (although I have not tested this)
source
I have pictures attached to a model. Those pictures are analyzed and the EXIF data is saved as metadata on the ActiveStorage::Blob.
class Foo < ApplicationRecord
has_one_attached :picture
end
There is an attribute on this model that I use for sorting the instances called order_date. This attribute has to be updated with the EXIF time after the blob got analyzed.
Using paperclip, a before_commit callback method was sufficient. With ActiveStorage, I also tried before_save and after_touch but both are not working.
How can I run code right after the ActiveStorage::AnalyzeJob has run successfully?
(I want to avoid monkey-patching ActiveStorage::AnalyzeJob, because it is also performed for other attachments.)
Thanks very much for your help!
I couldn't find anything official. I ended up overriding the analyze job since it is very simple anyways. It looks like below.
#/app/jobs/active_storage/analyze_job.rb
class ActiveStorage::AnalyzeJob < ActiveStorage::BaseJob
def perform(blob)
blob.analyze
blob.attachments.includes(:record).each do |attachment|
if attachment.record_type == 'Content'
record = attachment.record
record.set_file_info
record.save!
end
end
end
end
I have an application using Carrierwave to handle file uploads but really love the simplicity of ActiveStorage. There are plenty of tutorials on migrating from Paperclip to ActiveStorage with the former sunsetting development, but I see nothing on migrating from Carrierwave to ActiveStorage. Has anyone successfully done the migration and could point me in the right direction?
The procedure is really simple actually.
step 1:
configure the active store bucket. try to use a different bucket than your carrierwave one
step 2:
configure your model in order to provide access to the ActiveStorage. example
class Photo < AR::Base
mount_uploader :file, FileUploader # this is the current carrierwave implementation. Don't remove it
has_one_attached :file_new # this will be your new file
end
Now you will have two implementations for the same model. carrierwave access at file and ActiveStorage at file_new
step 3:
download images from Carrierwave and save it to active storage
This can be implemented in a rake file, activeJob etc..
Photo.find_each do |photo|
begin
filename = File.basename(URI.parse(photo.fileurl))
photo.file_new.attach(io: open(photo.file.url), filename: d.file )
rescue => e
## log/handle your errors in order to retry later
end
end
At this point you will have one image on the carrierwave bucket and the newly created image on the active storage bucket!
(optional)
step 4
Once you are ready with the migration modify your model changing the active storage accessor and remove the carrierwave integration
class Photo < AR::Base
has_one_attached :file # we changed the atachment name from file_new to file
end
This is a convenience option so your integration in controllers and other places remain intact. hopefully!
step 5
Update your records on active_storage_attachments table in order for the attachments be found as file and not file_new update column name from "file_new" to "file"
notes
Is possible to make some other tweaks to the application in order to handle things to consider
if your site will be running while you do the migration one way to fully operate would be implement active storage for new uploads then when you display images you can display active storage and carrierwave as a fallback
something like this in a helper:
photo.attached? ? url_for(photo.file_new) : photo.file.url
I hope this helps!
To begin with
You'll have to run this bundle exec rails active_storage:install
rails db:migrate
Replace mount_uploader :image, ImageUploader, to look like has_one_attached :image, in your model.
For rendering the image in the view, you should replace image_url with url_for(user.image).
You don't have to make any change to the controller code or in params, as the attribute image is already a strong parameter.
# user.rb
class User < ApplicationRecord
# mount_uploader :image, ImageUploader
has_one_attached :image
end
# show.html.erb
<%= image_tag url_for(user.image) %>
or
<%= image_tag user.image %>
I'm using Rails 5 with rails_admin and carrierwave gems.
I have a model Photo and and image uploader mounted on it (as per carrierwave documentation), looks roughly like this:
class Photo < ActiveRecord::Base
mount_uploader :image, ImageUploader
belongs_to :project
validates :name, presence: true
validates :image, presence: true
end
Given I have already some Photo objects created I can see a list of them in the rails_admin admin view.
And I start editing one of them
And I edit name
And I proceed to save it
Then rails admin fires some of it's magic and photo is being saved but after this action the image dissapears.
I have been digging a little in what request are being fired and rails_admin fires a PUT request with such params:
{
"authenticity_token"=>"xxx",
"photo"=>{
"name"=>"test2",
"description"=>"ewdeeweeefxxxwefwe",
"project_id"=>"3",
"image_cache"=>"",
"main"=>"0",
"about_us"=>"0"
},
"return_to"=>"http://localhost:3000/panel-admin/photo?model_name=photo", "_save"=>"", "model_name"=>"photo", "id"=>"29"}
and my Photo object is being update with not only name but also with image_url that of course overrides Image that already was mounted to the Photo
I have no idea why this is happening and how to prevent it.
Anyone might have encountered this issue and knows how to resolve it?
I found that. When I uncomment my custom filename method in uploader, it works well.
I'm currently building an app which has a model Post. I'm using the paperclip gem to upload images, and everything is going well.
class Post < ActiveRecord::Base
has_attached_file :headerimage, styles: {banner => "400x300#"}
end
As you can see by my class above, if I were to get a Post object, I could get the banner image with the following in my view:
image = Post.first.headerimage(:banner)
Alias
However, in my app, it must have the image attribute image refer to the thumbnail image. So, in my models class, I wrote
class Post < ActiveRecord::Base
has_attached_file :headerimage, styles: {banner => "400x300#"}
alias_attribute :image, :headerimage
end
which allows me to get an image by calling the following:
image = Post.first.image
This is what I want - however, it gets the original image from paperclip, so it is equivalent to writing the following:
image = Post.first.headerimage instead of image = Post.first.headerimage(:banner)
How can I set up a proper alias_attribute to access the paperclip thumnail? I can't seem to find an answer anywhere else, and I am unsure how paperclip is actually working.
I thought I might logically be able to do something like
alias_attribute :image, :headerimage(:banner)
but that does not work.
You can just try this - basically call the original with arguments since aliases won't take parameter but we know the fixed parameter to pass:
alias :image, :headerimage
def headerimage(name=nil)
headerimage(name || :thumb)
end