2011-09-23 2 views

risposta

18

Perché non usare MiniMagick? Modificato risposta di 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

Fantastico! La tua strada è davvero migliore. – Kir

+1

@skalee Sto ricevendo il seguente errore: Errno :: ENOENT in PhotosController # create Nessun file o directory - Perché, questo? – Gibson

+0

Penso che il codice abbia un errore. Se l'attributo dell'immagine è ': picture', dovresti aggiungere errori all'attributo': picture', non ': image' – Anwar

8

Mi ha sorpreso quanto fosse difficile cercare in giro per una via chiara per convalidare la larghezza dell'immagine & altezza con CarrierWave. @ La soluzione di Kir sopra è giusta, ma volevo fare un ulteriore passo avanti nello spiegare cosa ha fatto e le piccole modifiche che ho apportato.

Se si osserva il suo aspetto https://gist.github.com/1239078, la risposta si trova nella callback before :cache che ha nella classe Uploader. La linea di magia è

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

nel suo caso, avatar_upload_width & avatar_upload_height sono attributi del suo modello User. Non ho voglia di avere per memorizzare la larghezza & altezza nel database, così nel mio modello ho detto:

attr_accessor :image_width, :image_height 

Ricordate, è possibile utilizzare attr_accessor per gli attributi che si desidera avere a portata di mano quando si scherzi con un registrare, ma proprio non voglio persisterli al db. Così la mia linea magica in realtà trasformato in

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

Così ora ho la larghezza & altezza mia immagine memorizzata nel modello a oggetti. L'ultimo passo è quello di scrivere una convalida personalizzato per le dimensioni, così nel modello avete bisogno di qualcosa di simile a

validate :validate_minimum_image_size 

E poi sotto di essa a definire il metodo di convalida personalizzata, come nel l'essenza

# 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

Grazie per una spiegazione così profondo! – Kir

+2

Sono solo grato di aver trovato il codice di esempio su come farlo, è pazzesco come un'operazione così apparentemente comune sia così poco documentata! – DelPiero

12

ho fatto un validatore un po 'più completo in base alla risposta di @ 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 

utilizzarlo come validates :image, :image_size => {:min_width=>400, :min_height => 400}.

+0

È fantastico! – Kir

+0

Molto utile. Grazie per aver condiviso questo. –

+0

Grande lavoro uomo! –

5

Ho appena creato un validatore personalizzato che mira ad essere più sintattico per Rails 4+.
Ho preso idee dalle altre risposte su questo thread.
Ecco il succo del discorso: https://gist.github.com/lou/2881f1aa183078687f1e

e si può usare in questo modo:

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

In questo caso particolare che dovrebbe essere:

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