Valider la taille de l'image dans l'uploader de carrierwave

tous les téléchargements doivent être d'au moins 150x150 pixels. Comment le valider avec Carrierwave?

20
demandé sur Kir 2011-09-23 14:54:09

5 réponses

pourquoi ne pas utiliser MiniMagick? Modifié DelPiero de réponse:

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
18
répondu skalee 2012-06-03 11:48:55

j'ai fait un validateur légèrement plus complet basé sur la réponse de @skalee

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

Utiliser comme validates :image, :image_size => {:min_width=>400, :min_height => 400}.

12
répondu Phrodo_00 2013-01-29 13:20:38
8
répondu Kir 2011-09-24 07:33:41

cela m'a surpris à quel point il était difficile de chercher une façon claire de valider la largeur et la hauteur de l'image avec CarrierWave. La solution de @Kir ci-dessus est juste, mais je voulais aller plus loin en expliquant ce qu'il a fait, et les changements mineurs que j'ai faits.

Si vous regardez son gist https://gist.github.com/1239078, la réponse se trouve dans le before :cache callback qu'il a dans la classe Uploader. La magie est la ligne

model.avatar_upload_width, model.avatar_upload_height = `identify -format "%wx %h" #{new_file.path}`.split(/x/).map { |dim| dim.to_i }

dans son cas, avatar_upload_width & avatar_upload_height sont des attributs de son modèle d'Utilisateur. Je ne voulais pas pour stocker de la largeur et de la hauteur dans la base de données, donc, dans mon modèle, j'ai dit:

attr_accessor :image_width, :image_height

rappelez-vous, vous pouvez utiliser attr_accessor pour les attributs que vous voulez avoir sous la main en jouant avec un enregistrement, mais ne voulez tout simplement pas les persister dans la base de données. Donc ma ligne magique s'est transformée en

model.image_width, model.image_height = `identify -format "%wx %h" #{new_file.path}`.split(/x/).map { |dim| dim.to_i }

donc maintenant j'ai la largeur et la hauteur de mon image stockée dans l'objet model. Le la dernière étape est d'écrire une validation personnalisée pour les dimensions, donc dans votre modèle vous avez besoin de quelque chose comme

validate :validate_minimum_image_size

Et puis en dessous de définir personnalisé de votre méthode de validation, de même que dans les 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
8
répondu DelPiero 2012-02-28 16:42:43

je viens de faire un validateur personnalisé qui vise à être plus Rails 4+ syntaxe sympathique.

J'ai pris les idées des autres réponses sur ce fil.

Voici l'essentiel:https://gist.github.com/lou/2881f1aa183078687f1e

Et vous pouvez l'utiliser comme ceci:

validates :image, image_size: { width: { min: 1024 }, height: { in: 200..500 } }

Dans ce cas particulier, il devrait être:

validates :image, image_size: { width: 150, height: 150 }
5
répondu lou 2015-12-07 14:53:36