ruby on rails - tutorial - Método indefinido de cultivo! Uso de Carrierwave con MiniMagick sobre rieles 3.1.3
rails carrierwave image_tag (3)
Me estaba costando muchísimo conseguir que esto funcionara, y todavía lo soy. Llegaré al corazón de ello. Estoy siguiendo el tutorial de Ryan Bates para hacer que el recorte funcione con Jcrop y Carrierwave. Opté por utilizar MiniMagick porque incluso después de reinstalar ImageMagick y RMagick en mi máquina, aparece un error que destruye el servidor de rieles en mi máquina local. De todos modos cambiando a MiniMagick me lo arreglé. Así que todo está muy bien hasta este punto. Se están produciendo imágenes de diferentes tamaños y se están cargando con éxito. Pero una vez que intento recortar me sale este error:
undefined method `crop!'' for #<MiniMagick::CommandBuilder:0x000001052e4608>
Esto me confunde mucho porque estoy usando casi el mismo código que Bates:
def crop
if model.crop_x.present?
resize_to_limit(700, 700)
manipulate! do |img|
x = model.crop_x.to_i
y = model.crop_y.to_i
w = model.crop_w.to_i
h = model.crop_h.to_i
img.crop!(x, y, w, h)
end
end
end
De todos modos, es ese método de cultivo el que está fallando. Así que pensé, ese es un comando de ImageMagick ... Entonces miré el doco de ImageMagick, y no pude encontrar el método de recorte con la explosión, así que lo intenté sin él, y luego el error se convierte en esto:
No such file or directory - /var/folders/dF/dFNM2+Y7FVScn4+OxVHKOU+++TI/-Tmp-/mini_magick20111207-34409-1tnaa07.jpg
De todos modos, algo no tiene mucho sentido para mí, ¡cualquier ayuda sería apreciada! ¡Gracias por leer!
En breve:
img.crop("#{size}#{offset}") # Doesn''t return an image...
img # ...so you''ll need to call it yourself
Aquí hay una mejor explicación de por qué sucedió esto en lugar de una solución de estilo cortar / pegar.
RMagick y MiniMagick no son intercambiables. RMagick tiene un DSL muy parecido a Ruby y, como tal, emplea métodos que toman múltiples argumentos:
rmagick_image.crop(x_offset, y_offset, width, height) # Returns an image object
rmagick_image.crop!(x_offset, y_offset, width, height) # Edits object in place
MiniMagick en su lugar genera dinámicamente métodos al iterar a través de una lista de MOGRIFY_COMMANDS
que coinciden con numerosas opciones con prefijo de guión especificadas en la documentación de mogrify
de ImageMagick . Cada uno de esos métodos pasa sus argumentos directamente a mogrify
y ninguno devuelve un objeto de imagen:
minimagick_image.crop(''100x200'') # Translates to `mogrify -crop 100x200 image.ext`
minimagick_image.polaroid(''12'') # Executes `mogrify -polaroid 12 image.ext`
En especie, RMagick tiene crop!
y MiniMagick no lo hace.
De acuerdo con los documentos de ImageMagick, mogrify -crop
toma una geometry
argumento. El argumento de la geometry
se explica here . Notará que todos esos argumentos son cadenas, por lo que en lugar de crop(100,200)
usaría crop(''100x200'')
o crop(''100%)
. No es muy parecido a Ruby, pero eso es parte de lo que hace que MiniMagick sea tan liviano.
Con ese conocimiento, podemos deducir cómo recortar con MiniMagick. mogrify -crop
puede tomar una geometría como un width
cadena x height
+ xoffset
+ yoffset
, por lo que solo necesitamos construir una cadena similar.
Teniendo en cuenta w
, h
, x
, puede usar cualquiera de las siguientes opciones que encuentre más legibles:
# Concatenating plus signs with plus signs is atrociously confusing.
# Recommended only if you want to drive your future self insane.
mogrify_arg = w + ''x'' + h + ''+'' + x + ''+'' + y
# Readable but inefficient
mogrify_arg = [ w, ''x'', h, ''+'', x, ''+'', y ].join('''')
# Questionable readability
mogrify_arg = "#{w}x#{h}+#{x}+#{y}"
# Slick, performant, but potentially risky: `<<` modifies the receiving object in place
# `w` is actually changing here to "WxH+X+Y"...
mogrify_arg = w << ''x'' << h << ''+'' << x << ''+'' << y
# A lovely, self-documenting version
size = w << ''x'' << h
offset = ''+'' << x ''+'' << y
mogrify_arg = "#{size}#{offset}"
Aquí hay un ejemplo completo:
def crop
if model.crop_x.present?
resize_to_limit(700, 700)
manipulate! do |img|
x = model.crop_x
y = model.crop_y
w = model.crop_w
h = model.crop_h
size = w << ''x'' << h
offset = ''+'' << x << ''+'' << y
img.crop("#{size}#{offset}") # Doesn''t return an image...
img # ...so you''ll need to call it yourself
end
end
end
Pude hacer que esto funcionara al agregar los parámetros X e Y al comando de recorte como lo indica @ mikhail-nikalyukin
def crop
manipulate! do |img|
img.crop "750x600+0+0"
img.strip
img = yield(img) if block_given?
img
end
end
Tenía los mismos problemas, mi solución fue este método.
def cropped_image(params)
image = MiniMagick::Image.open(self.image.path)
crop_params = "#{params[:w]}x#{params[:h]}+#{params[:x]}+#{params[:y]}"
image.crop(crop_params)
image
end
Solo modifica mi método para tu caso.
La clave está en qué formato pasan las variables al método de recorte, espero que esto le ayude.