开发者

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 }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜