Paperclip validating when no attachment - ruby-on-rails

I have a rails model in which an image is uploaded using Paperclip.
I have added validation of size for the image.
validates_attachment-size :image, less_than => 5.megabytes
When trying to save the model when there is no attachment it validates the image which is absent and fails the save.
I need to save the model if there is no image and the validation should work only when there is an image.

First of you have a typo in your code. validates_attachment-size should be validates_attachment_size.
You wanted to do:
validates_attachment_size :image, less_than => 5.megabytes
This built in helper would work normally. But, this validation will force the validation of an actual attachment, means it won't work if the image is not present.
So, if you want to be sure if an image is present, you can add a custom validator where you will check the image presence. Like this:
validate :image_presence_and_size
def image_presence_and_size
if image.present? && image_file_size < 5.megabytes
errors.add(:file_size, "file size must be less than 5 megabytes.")
end
end

Try the following code.
validate :image_present
def image_present
if image.present? && image_file_size < 2.megabytes
errors.add(:file_size, "file size must be between 0 and 2 megabytes.")
end
end
Here, the validation will work if there is image present in the model and will skip the validation if there is no image.

Related

upload image to multiple models in rails

I am using carrierwave and Minimagick gem to upload an attachment to S3. Now I want to save the some.pdf in two models(ie, assignment, and message). I give the same parameters in attachment field to save in two tables. But the second table attachment saves blurry. First one gets clear view of attachment.
My controller codes like,
#assignment = Assignment.new(assignment_params)
#message = Message.new
begin
Message.transaction do
asign_att = params[:assignment][:attachment]
#assignment.save!
#message.attachment = asign_att
#message.save!
end
end
My model has,
(in attachment.rb) mount_uploader :attachment, AttachmentUploader
(in message.rb) mount_uploader :attachment, ImageUploader
I want to save same file into two models with clear view. What I want to do? Thanks in advance.
Check in your second table uploader file if you have specified any version or something like that.
With version you can create clones of attachment in different resolutions like this.
version :thumb do
process resize_to_fit 50, 50
end
I would use a callback to do this, something like:
after_commit :assign_to_models
def assign_to_models
...
end
IMHO, I would create an model that has all the carrierwave attachements, and have it belongs both to message and attachement.
I hope this helps

Storing an image based upon nothing but a URL in Paperclip

I am using paperclip for a profile picture upload feature in my rails app. This works nicely for the default case of uploading images to a profile, but I want to allow users without a picture to pick from one of a selection of precanned 'stock' images.
These images are hosted locally, within my assets images folder. Therefore on these occasions I want to be able to add an image to my EventImage object without actually uploading an image, more just referencing a URL at a local path.
I have tried pretty much every answer from this post : Save image from URL by paperclip but none of them seem to work. I am using paperclip version paperclip (4.3.1 37589f9)
When I try the solution of :
def photo_from_url(url)
puts "we got:"+url
Thread.new do
self.photo = URI.parse(url)
end
end
It results in no image reference being stored, and regardless of the URL to an image I pass into that method, it never displays my image when I do : <%= image_tag #event.event_images.first.photo.url %> - instead it shows the default image for when an image has not been located or stored.
I also have to put it in a new thread otherwise it gets tied up and blocks / resulting in a timeout which seems to be a problem with URI.parse, also the image ends up failing validation as photo is 'empty' which is not allowed in my validation, so I end up removing the validation presence line on :photo, which still does not solve the problem. I really just want the models paperclip method :photo - to point to a local url sometimes, and my correctly normally uploaded files other times.
See the whole class here:
# == Schema Information
#
# Table name: event_images
#
# id :integer not null, primary key
# caption :string
# event_id :integer
# created_at :datetime not null
# updated_at :datetime not null
# photo_file_name :string
# photo_content_type :string
# photo_file_size :integer
# photo_updated_at :datetime
#
class EventImage < ActiveRecord::Base
attr_accessor :PAPERCLIP_STORAGE_OPTS
has_attached_file :photo , PAPERCLIP_STORAGE_OPTS
validates_attachment_presence :photo
validates_attachment_content_type :photo, :content_type => ["image/jpg", "image/jpeg", "image/gif", "image/png"]
validates_with AttachmentSizeValidator, :attributes => :photo, :less_than => 3.megabytes
belongs_to :event
def photo_from_url(url)
Thread.new do
self.photo = URI.parse(url)
end
end
end
Instead, I have decided that it would be best to add a 'canned_image_id' to the EventImage model, then use a photo_url method in the model which can choose to return either the paperclip url or the canned image url depending on whether or not the image is a canned image. It also hides this complexity behind a helper method :)

creating an alias_attribute for a paperclip image in Rails

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

Carrierwave: How to validate that image is attached? (either upload, or remote_url)

I'm trying to make sure that every instance of Picture model has a file attached.
In other words - there are two fields in the form:
:file
:remote_file_url
I want user to fill in at least one of them.
When I validate presence of :file, and submit remote_file_url instead of file - then it gives validation error.
The only way I found for now is do smth like this:
class Picture < ActiveRecord::Base
validate :file_xor_remote_file_url
private
def file_xor_remote_file_url
if !(file.blank? ^ remote_file_url.blank?)
errors.add(:base, "Specify a file to upload, or file URL, not both")
end
end
end
The wiki says you can validate your upload like this:
mount_uploader :avatar, AvatarUploader
validates_presence_of :avatar
It doesn't mention any different handling for remote URLs, but underlines that Carrierwave validates the presence of the file rather than just the presence of an URL. So a given remote URL must refer to a valid file that can be uploaded.
You said that "validate presence of :file", but perhaps this could be the point. Hope this helps.

Smarter paperclip validations

I'm using paperclip in a rails app and have the following three validations in my model
validates_attachment_presence :photo
validates_attachment_size :photo, :less_than=>1.megabyte
validates_attachment_content_type :photo, :content_type=>['image/jpeg', 'image/png', 'image/gif']
If the user forgets to add an attachment, all three validations fail and thus, the user is presented with the following three errors:
# Photo file name must be set.
# Photo file size file size must be between 0 and 1048576 bytes.
# Photo content type is not included in the list
I think it would be best to just show the first error in this instance since the other two errors are purely consequential... I would prefer the user to only ever see the second two errors if an attachment has been added but doesn't meet the validation criteria.
I'm certain there is no pre-baked validation that does this sort of thing and from reading the code in vendor/plugins/paperclip/lib/paperclip.rb I see that the validates_attachment_size method supports the :unless parameter as shown:
def validates_attachment_presence name, options = {}
message = options[:message] || "must be set."
validates_presence_of :"#{name}_file_name",
:message => message,
:if => options[:if],
:unless => options[:unless]
end
So, I was thinking that I could do something like the following:
validates_attachment_size :photo, :less_than=>1.megabyte, :unless=> :photo.blank
But that breaks the app. Anyone have any experience of doing this sort of thing? Would be a nice contribution to the paperclip source code.
EDIT:
I've tried using this:
validates_attachment_size :photo, :less_than=>1.megabyte,
:unless=> Proc.new { |image| image[:photo].nil? }
It doesn't quite work though as I've just managed to upload a 5mb mp3 with this validation in place. But it's promising as the error message doesn't appear when the user has not attached a photo.
validates_attachment_size :photo, :less_than => 1.megabyte,
:unless => Proc.new { |imports| imports.photo_file_name.blank? }
I think you can do it other way. Don't mess with validations. You probably have something like this in your form:
<%= f.error_messages %>
You can remove it and write your own helper to display error messages. Errors are stored in hash:
#photo.errors
Or if you want to get to them through form builder:
f.object.errors

Resources