2011-09-23 11 views

Respuesta

18

¿Por qué no usar MiniMagick? respuesta modificada de DelPiero:

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

¡Genial! Tu camino es realmente mejor. – Kir

+1

@skalee Recibo el siguiente error: Errno :: ENOENT en PhotosController # create No existe tal archivo o directorio -, ¿Por qué es esto? – Gibson

+0

Creo que el código tiene un error. Si su atributo de imagen es ': picture', agregaría errores al atributo': picture', no ': image' – Anwar

8

Me sorprendió lo difícil que era para buscar alrededor para una manera clara para validar ancho de la imagen & altura con CarrierWave. La solución anterior de @ Kir está en lo cierto, pero quería dar un paso más para explicar lo que hizo y los pequeños cambios que hice.

Si nos fijamos en lo esencial su https://gist.github.com/1239078, la respuesta está en la devolución de llamada before :cache que tiene en la clase Uploader. La línea mágica es

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

en su caso, avatar_upload_width & avatar_upload_height son atributos de su modelo de usuario. No quería que tienen para almacenar ancho & altura en la base de datos, por lo que en mi modelo dije:

attr_accessor :image_width, :image_height 

Recuerde, puede utilizar attr_accessor para los atributos que desea tener en la mano cuando jugar con una grabar, pero simplemente no quiero persistirlos a la base de datos. Así que mi línea mágica realidad convertido en

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

así que ahora tengo el ancho & altura de mi imagen almacenada en el objeto del modelo. El último paso es escribir una validación personalizada para las dimensiones, por lo que en el modelo que necesita algo así como

validate :validate_minimum_image_size 

Y entonces por debajo de ella a definir su método de validación personalizada, igual que en la esencia

# 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 
+0

Gracias por una explicación tan profunda! – Kir

+2

Estoy agradecido de haber encontrado la muestra de tu código de cómo hacerlo, ¡es una locura que una operación tan aparentemente tan poco documentada! – DelPiero

12

me hizo un validador poco más completo basado en la respuesta 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 

usarlo como validates :image, :image_size => {:min_width=>400, :min_height => 400}.

+0

¡Eso es increíble! – Kir

+0

Muy útil. Gracias por compartir esto. –

+0

¡Gran hombre de trabajo! –

5

Acabo de hacer un validador personalizado que pretende ser más sintaxis de Rails 4+ amigable.
Tomé ideas de las otras respuestas en este hilo.
Aquí está el quid: https://gist.github.com/lou/2881f1aa183078687f1e

y se puede utilizar de esta manera:

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

En este caso particular que debe ser:

validates :image, image_size: { width: 150, height: 150 } 
Cuestiones relacionadas