Validate image size in carrierwave uploader
All uploads s开发者_开发百科hould be at least 150x150 pixels. How to validate it with Carrierwave?
Why not to use MiniMagick? Modified DelPiero's answer:
validate :validate_minimum_image_size
def validate_minimum_image_size
image = MiniMagick::Image.open(picture.path)
unless image[:width] > 400 && image[:height] > 400
errors.add :image, "should be 400x400px minimum!"
end
end
I made a slightly more complete validator based on @skalee's answer
class ImageSizeValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
unless value.blank?
image = MiniMagick::Image.open(value.path)
checks = [
{ :option => :width,
:field => :width,
:function => :'==',
:message =>"Image width must be %d px."},
{ :option => :height,
:field => :height,
:function => :'==',
:message =>"Image height must be %d px."},
{ :option => :max_width,
:field => :width,
:function => :'<=',
:message =>"Image width must be at most %d px."},
{ :option => :max_height,
:field => :height,
:function => :'<=',
:message =>"Image height must be at most %d px."},
{ :option => :min_width,
:field => :width,
:function => :'>=',
:message =>"Image width must be at least %d px."},
{ :option => :min_height,
:field => :height,
:function => :'>=',
:message =>"Image height must be at least %d px."},
]
checks.each do |p|
if options.has_key?(p[:option]) and
!image[p[:field]].send(p[:function], options[p[:option]])
record.errors[attribute] << p[:message] % options[p[:option]]
end
end
end
end
end
Use it like validates :image, :image_size => {:min_width=>400, :min_height => 400}
.
It surprised me just how difficult it was to search around for a clear-cut way to validate image width & height with CarrierWave. @Kir's solution above is right on, but I wanted to go a step further in explaining what he did, and the minor changes I made.
If you look at his gist https://gist.github.com/1239078, the answer lies in the before :cache
callback he has in the Uploader class. The magic line is
model.avatar_upload_width, model.avatar_upload_height = `identify -format "%wx %h" #{new_file.path}`.split(/x/).map { |dim| dim.to_i }
in his case, avatar_upload_width & avatar_upload_height are attributes of his User model. I didn't want to have to store width&height in the database, so in my model I said:
attr_accessor :image_width, :image_height
Remember, you can use attr_accessor for attributes you want to have on hand when messing with a record, but just don't want to persist them to the db. So my magic line actually turned into
model.image_width, model.image_height = `identify -format "%wx %h" #{new_file.path}`.split(/x/).map { |dim| dim.to_i }
So now I have the width & height of my image stored in the model object. The last step is to write a custom validation for the dimensions, so in your model you need something like
validate :validate_minimum_image_size
And then below it define your custom validation method, same as in the gist
# custom validation for image width & height minimum dimensions
def validate_minimum_image_size
if self.image_width < 400 && self.image_height < 400
errors.add :image, "should be 400x400px minimum!"
end
end
I just made a custom validator that aims to be more Rails 4+ syntax friendly.
I took ideas from the others responses on this thread.
Here is the gist: https://gist.github.com/lou/2881f1aa183078687f1e
And you can use it like this:
validates :image, image_size: { width: { min: 1024 }, height: { in: 200..500 } }
In this particular case it should be:
validates :image, image_size: { width: 150, height: 150 }
精彩评论