Tag: Rails

Paperclip – walidacja rozmiaru obrazków(grafik) – podejście drugie

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

Paperclip minimum resolution validation extension

Rails3, rails.js i document.on is not a function

Pracując dzisiaj nad Senpuu v5 - zauważyłem że Susanoo (autorski CMS pod Senpuu) nie pokazuje JSowych confirmów. Przykładowo coś takiego:

link_to "Usuń notkę", :confirm=>"Czy jesteś pewien?", :method=>"delete"

nie działało. JS ładował się prawidłowo, jednak po włączeniu Firebuga, natknąłem się na taki oto błąd:

document.on is not a function

A po kliknięciu, zamiast wysyłać żądanie usunięcia, realizowane było normalne "linkowe".

Firebug dokładnie wskazywał na tę metodę:

document.on("click", "a[data-method]", function(event, element) {
  if (event.stopped) return;
    handleMethod(element);
    event.stop();
  });

Okazało się, że Rails3 korzysta z nowego Prototype 1.7 - a ja przez przypadek wkleiłem stare. Komunikat zniknął po przywróceniu nowej wersji Prototype. Wziąć ją można z internetu lub generując sobie nowy projekt:

rails new givemeprototype

i kopiując odpowiednie pliki z /public/javascripts/.

Copyright © 2025 Closer to Code

Theme by Anders NorenUp ↑