image processing does not work. It raises undefined method `resize_to_limit' error in background jobs. I was using the repository version of shrine gem and this started happening after bundle update
Ruby version:
ruby '2.4.2'
Shrine version:
shrine (2.10.1)
You probably updated ImageProcessing to version 1.0. The ImageProcessing gem has changed it's API in version 1.0, see the README.
TL;DR: This code
class ImageUploader < Shrine
include ImageProcessing::MiniMagick
plugin :processing
plugin :versions
process(:store) do |io, context|
original = io.download
size_800 = resize_to_limit(original, 800, 800)
size_500 = resize_to_limit(original, 500, 500)
size_300 = resize_to_limit(original, 300, 300)
original.close!
{ original: io, large: size_800, medium: size_500, small: size_300 }
end
end
now becomes
class ImageUploader < Shrine
plugin :processing
plugin :versions
process(:store) do |io, context|
original = io.download
pipeline = ImageProcessing::MiniMagick.source(original)
size_800 = pipeline.resize_to_limit!(800, 800)
size_500 = pipeline.resize_to_limit!(500, 500)
size_300 = pipeline.resize_to_limit!(300, 300)
original.close!
{ original: io, large: size_800, medium: size_500, small: size_300 }
end
end
@janko-m thank you, that fixed that problem but now I get this error
Shrine::InvalidFile (#<ImageProcessing::Builder:0x00007fcfbfb3a588 @options={:source=>#<Tempfile: (closed)>, :loader=>{}, :saver=>{}, :fo
rmat=>nil, :operations=>[[:resize_to_limit, [#<Tempfile: (closed)>, 4746, 4746]]], :processor_class=>ImageProcessing::MiniMagick::Processor}> is not a valid IO object (it doesn't respond to #read, #eof?, #rewind, #close))
what else is changed in api?
It looks like it's trying to upload the image_processing::builder as a version instead of a processed image file. This can happen if you didn't use the the bang method (resize_to_limit!) for resize_to_limit in Janko's example above. 馃檪
@janko-m I think we should explicitly add a comment saying "Use bang method" or "Not bang method" whenever we answer questions and switch the methods. 馃槂
@hmistry Thanks for hopping in!
I think we should explicitly add a comment saying "Use bang method" or "Not bang method" whenever we answer questions and switch the methods.
I'm not sure what you mean by this. It's true that users that used ImageProcessing prior to 1.0 might be surprised that the "bang" doesn't mean "process in-place" anymore, and that processing in-place was actually removed in ImageProcessing 1.0. Is this way you meant? I'm thinking that we could just point anyone asking the same question to this ticket.
@janko-m Sorry I wasn't clear. I was thinking this is the third or forth time we've answered support questions where the user missed that we used the bang method or switched it. This has happened before the IP 1.0 release so nothing to do with the new release. My idea is that whenever we do a code sample that involves use of a bang method, we can add a comment explicitly stating use of bang method, or if we ask them to switch from bang to not bang or vice versa. Lets see if the comment catches their attention.
size_800 = pipeline.resize_to_limit!(800, 800) #use bang method
size_800 = pipeline.resize_to_limit(800, 800).call #use non-bang method
@janko-m @hmistry changed to use the bang method and error is gone now. But now when passing upload to background it raises this error
Error performing ImageUploadJob (Job ID
: 8bb00f63-f8e8-475b-843c-6870af5de201) from DelayedJob(image) in 661.05ms: ArgumentError (wrong number of
arguments (given 4, expected 3))
I checked everything and all seems fine, cannot figure it out
Can you post your uploader code here?
Here it is
class ImageUploader < Shrine
plugin :processing
plugin :versions
plugin :validation_helpers
plugin :upload_options, store: -> (io, context) do
{ metadata_directive: "REPLACE" } if io.is_a?(Shrine::UploadedFile)
end
process(:store) do |io, context|
original = io.download
pipeline = ImageProcessing::MiniMagick.source(original)
size_4746 = pipeline.resize_to_limit!(original, 4746, 4746)
size_2160 = pipeline.resize_to_limit!(size_4746, 2160, 2160)
size_2048 = pipeline.resize_to_limit!(size_2160, 2048, 2048)
size_1024 = pipeline.resize_to_limit!(size_2048, 1024, 1024)
original.close!
{original: io, x4746: size_4746, x2160: size_2160, x2048: size_2048, x1024: size_1024 }
end
Attacher.validate do
validate_mime_type_inclusion %w[image/jpeg image/png image/gif], message: "Image must be JPEG, PNG or GIF"
validate_max_size 4.megabytes
end
end
The new #resize_to_limit! method only accepts dimensions now, the source image is given separately in #source or #call. The direct translation of your code would be using #call instead of #source (notice that we're now calling #resize_to_limit without a bang)
original = io.download
pipeline = ImageProcessing::MiniMagick
size_4746 = pipeline.resize_to_limit(4746, 4746).call(original)
size_2160 = pipeline.resize_to_limit(2160, 2160).call(size_4746)
size_2048 = pipeline.resize_to_limit(2048, 2048).call(size_2160)
size_1024 = pipeline.resize_to_limit(1024, 1024).call(size_2048)
original.close!
{ original: io, x4746: size_4746, x2160: size_2160, x2048: size_2048, x1024: size_1024 }
But I don't recommend generating thumbnails from other thumbnails anymore, because information is lost after a resize and the result ends up slightly blurry, though the new ImageProcessing versions remedy that by sharpening the thumbnails after resize. However, this way any information loss and now sharpening will be more and more multiplied.
I would recommend generating all thumbnails from the same source image (notice the #source and #resize_to_limit! with a bang now):
original = io.download
pipeline = ImageProcessing::MiniMagick.source(image)
size_4746 = pipeline.resize_to_limit!(4746, 4746)
size_2160 = pipeline.resize_to_limit!(2160, 2160)
size_2048 = pipeline.resize_to_limit!(2048, 2048)
size_1024 = pipeline.resize_to_limit!(1024, 1024
original.close!
{ original: io, x4746: size_4746, x2160: size_2160, x2048: size_2048, x1024: size_1024 }
This will be slower, but thumbnails will be more correct.
Most helpful comment
You probably updated ImageProcessing to version 1.0. The ImageProcessing gem has changed it's API in version 1.0, see the README.
TL;DR: This code
now becomes