Nie tak dawno temu opublikowałem wpis w którym pokazuję jak zrobić walidację minimalnego rozmiaru obrazka z wykorzystaniem Paperclipa. Podejście to było (i jest) proste, jednak okazało się niewystarczające (niewygodne) gdy mamy do czynienia z kilkoma plikami graficznymi na model. Z tego względu przebudowałem tę metodę, tak aby wydzielić ja do samego Paperclipa. Mimo że wyszła wersja 2.3.8 Paperclipa, sam korzystam z lekko zmodyfikowanej przeze mnie 2.3.6, która działa na Rails3. Kod ten powinien działać na każdej wersji Paperclipa.
module Paperclip module ClassMethods def validates_attachment_minimum_resolution name, options = {} validation_options = options.dup validates_each(name, validation_options) do |record, attr, value| unless record.errors.include?(name) m_width = options[:width] m_height = options[:height] message = options[:message] || "must be bigger." message = message.call if message.is_a?(Proc) image = record.send(name) if image && image.queued_for_write[:original] dimensions = Paperclip::Geometry.from_file(image.queued_for_write[:original]) if dimensions.width < m_width || dimensions.height < m_height if record.errors.method(:add).arity == -2 record.errors.add(:"#{name}", message) else record.errors.add(:"#{name}", :inclusion, :default => options[:message], :value => value) end end end end end end end end
Wrzucamy do /lib/extensions, podpinamy w /config/application.rb:
require 'extensions/paperclip'
I używamy. A jak działa? Załóżmy że mamy mieć miniaturkę (:thumb), która ma mieć rozdzielczość minimum 300x300 i być w formacie JPG:
TYPES = ['image/jpeg', 'image/jpg', 'image/pjpeg'] FILE_MAX_SIZE = 2048 has_attached_file :thumb, :styles => {:mini => "120x95\#", :standard => "190x150\#", :big => "300x300>"}, :url => "/images/models/thumb/:id_:style.:extension", :default_style => :standard validates_attachment_presence :thumb, :message => 'musi być dołączony' validates_attachment_size :thumb, :less_than => FILE_MAX_SIZE.kilobytes, :message => "musi mieć mniej niż #{FILE_MAX_SIZE} kb" validates_attachment_content_type :thumb, :content_type => TYPES, :message => "ma nieprawidłowy format" validates_attachment_minimum_resolution :thumb, :width => 300, :height => 300, :message => "mus mieć minimum 300px na 300px"
Ważne jest aby sprawdzać typ pliku przed sprawdzeniem rozmiarów, ponieważ walidacja ta nie uruchomi się jeśli plik zostanie uznany przez wcześniejsze walidacje za niepoprawny.
Warto zauważyć, że można to internacjonalizować. Mamy w kodzie taki fragment:
message = message.call if message.is_a?(Proc)
Dzięki któremu możemy zrobić w kodzie tak:
:message => lambda{I18n.t("activerecord.errors.messages.paperclip.res", { :width => 300, :height => 300})}
I mieć inny komunikat zależnie od języka.
Warto wspomnieć też, że walidacja ta (tak jak reszta paperclipowych) przeprowadzana jest tylko jeśli wymuszamy podstawową walidację obecności pliku:
validates_attachment_presence :thumb
Aby uruchamiać walidację tylko jeśli plik został do formularza dołączony (ale formularz może być bez pliku), można zrobić tak:
validates_attachment_presence :thumb, :message => "musi istnieć", :if => Proc.new { |imports| imports.thumb.file? }
Lub, można też dopisać sobie taką metodę do naszego rozszerzenia i będzie to za nas robione automatycznie:
def validates_attachment_if_included name, options = {} options[:if] = Proc.new { |imports| imports.send(name).file? } validates_attachment_presence name, options end
Przykład:
validates_attachment_if_included :thumb
Leave a Reply