rails notidentifiedbyimagemagickerror missingrequiredvalidatorerror game errors ruby-on-rails ruby-on-rails-3 paperclip

ruby on rails - notidentifiedbyimagemagickerror - Guardar las dimensiones de las imágenes(ancho y alto) en Paperclip?



paperclip::errors::missingrequiredvalidatorerror (6)

Cuando un usuario carga una imagen con clip, la proceso con el siguiente modelo:

class Picture < ActiveRecord::Base has_attached_file :pic, :styles => { :small => "100x100>" }, :whiny => true after_save :save_geometry def save_geometry unless @geometry_saved self.original_geometry = get_geometry(:original) self.small_geometry = get_geometry(:small) @geometry_saved = true self.save end end def get_geometry(style = :original) begin Paperclip::Geometry.from_file(pic.path(style)).to_s end end end

La función get_geometry llama a ImageMagick identify para encontrar la geometría de sus imágenes originales y redimensionadas.

Guardo los resultados en un campo de base de datos. Por ejemplo, si subí una imagen que era 1024x768 mis campos en caché contendrían:

original_geometry = "1024x768" small_geometry = "100x75"

Cualquier asistente de Paperclip sabe si puede usar Paperclip para guardar una imagen, también guarda las dimensiones de la imagen (ancho y alto) en 2 campos adicionales. ¿Cómo se obtienen esos datos durante el proceso de carga de Paperclip?


Encontré la solución más simple: gema Fastimage (link)

Es rápido y muy, muy simple. Ejemplo:

require ''fastimage'' FastImage.size("/some/local/file.gif") => [266, 56] # width, height FastImage.type("/some/local/file.gif") => :gif


La gema paperclip-meta almacena en caché las dimensiones de la imagen y el tamaño del archivo para todos los estilos de imagen. Se hace referencia en el Paperclip README. El paperclip-meta repo está aquí: https://github.com/teeparham/paperclip-meta


Necesitarás requerir ''RMagick''

uploaded_image = Magick::Image.read(image).first #image is what you''ve specified in paperclip to be your image width = uploaded_image.columns height = uploaded_image.rows

Sin embargo, no estoy seguro de cómo hacerlo funcionar con las devoluciones de llamada. Tal vez algo así como:

attr_accessor :write_image_dimensions? before_save :check_image_changed def check_image_changed self.write_image_dimensions? = image_changed? end after_save :write_image_dimensions, :if => :write_image_dimensions? def write_image_dimensions uploaded_image = Magick::Image.read(image).first #image is what you''ve specified in paperclip to be your image self.width = uploaded_image.columns self.height = uploaded_image.rows save end


Solo para completar, aunque las respuestas anteriores ya muestran sugerencias bastante buenas.

Puede utilizar manejadores de eventos Paperclip en lugar de devoluciones de llamada de Rails. En este caso, el tamaño se volverá a calcular solo cuando la imagen cambie. (Si está utilizando S3 para almacenamiento, esto puede ahorrar bastante tiempo)

has_attached_file :image, :styles => ... after_post_process :save_image_dimensions def save_image_dimensions geo = Paperclip::Geometry.from_file(image.queued_for_write[:original]) self.image_width = geo.width self.image_height = geo.height end

La imagen ni siquiera tiene que descargarse de S3 (o leer de un archivo), el clip lo proporciona al controlador de eventos.

Ver la sección de Eventos del archivo léame para más detalles.


Uso de Rails 4 Utilizo la siguiente Preocupación para guardar las dimensiones de la imagen:

module Dimensions extend ActiveSupport::Concern included do end module ClassMethods def extract_dimensions_for *fields define_method(:extract_dimensions_field_list) { fields } before_save :extract_dimensions fields.each do |f| serialize (f.to_s+"_dimensions"), Hash class_eval do [:width, :height].each do |axis| define_method("#{f}_#{axis}") do return send(f.to_s+"_dimensions")[axis] end end define_method("#{f}_dimensions_max") do |width, height=nil| dims = send(f.to_s+"_dimensions") rw = width.to_f / dims[:width] rh = height.to_f / dims[:height] if height r = (!height || rw < rh) ? rw : rh return {width: (dims[:width] * r).to_i, height: (dims[:height] * r).to_i} end define_method("#{f}_is_portrait?") do dims = send(f.to_s+"_dimensions") return dims[:width] <= dims[:height] end define_method("#{f}_is_landscape?") do dims = send(f.to_s+"_dimensions") return dims[:width] > dims[:height] end end end class_eval do def extract_dimensions extract_dimensions_field_list.each do |f| tempfile = send(f).queued_for_write[:original] unless tempfile.nil? geometry = Paperclip::Geometry.from_file(tempfile) self.send(f.to_s+"_dimensions=", {width: geometry.width.to_i, height: geometry.height.to_i}) end end end end end end end

Entonces en tu modelo:

... include Dimensions extract_dimensions_for :image ...

Esto guardará sus dimensiones en un campo serializado llamado image_dimensions así como también agregará algunos otros métodos image_width , image_height y image_dimensions_max(width, height)