I have uploaders for different types of images. Each has the same set of derivatives (large, medium, thumbnail), but different resolutions. But they also share some configuration. For example, each uploader converts the original to jpeg, changes quality and strips metadata.
class BannerUploader < Shrine
Attacher.derivatives do |original|
magick = ImageProcessing::MiniMagick.source(original)
.convert('jpg')
.saver(quality: 85)
.strip
{
large: magick.resize_to_limit!(1600, 400),
medium: magick.resize_to_limit!(800, 200),
thumbnail: magick.resize_to_limit!(400, 100)
}
end
end
This one has the same processing rules:
class PhotoUploader < Shrine
Attacher.derivatives do |original|
magick = ImageProcessing::MiniMagick.source(original)
.convert('jpg')
.saver(quality: 85)
.strip
{
large: magick.resize_to_limit!(1200, 1200),
medium: magick.resize_to_limit!(600, 600),
thumbnail: magick.resize_to_limit!(300, 300)
}
end
end
Is it possible to extract and share some of the configuration (like .convert('jpg').saver(quality: 85).strip
) between those uploaders? Something similar to validations inheritance or a helper.
There isn't anything for sharing processing logic out-of-the-box, but you can create a service object, for example:
class BannerUploader < Shrine
Attacher.derivatives do |original|
Thumbnails.call(original, {
large: [1600, 400],
medium: [800, 200],
thumbnail: [400, 100],
})
end
end
class PhotoUploader < Shrine
Attacher.derivatives do |original|
Thumbnails.call(original, {
large: [1200, 1200],
medium: [600, 600],
thumbnail: [300, 300],
})
end
end
class Thumbnails
def self.call(original, sizes)
magick = ImageProcessing::MiniMagick.source(original)
.convert('jpg')
.saver(quality: 85)
.strip
thumbnails = {}
sizes.each do |name, (width, height)|
thumbnails[name] = magick.resize_to_limit!(width, height)
end
thumbnails
end
end