Shared derivatives configuration for multiple Shrine uploaders

97 Views Asked by At

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.

1

There are 1 best solutions below

1
Janko On BEST ANSWER

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