module Shrine::Plugins::Versions

  1. lib/shrine/plugins/versions.rb

The versions plugin enables your uploader to deal with versions, by allowing you to return a Hash of files when processing.

plugin :versions

Here is an example of processing image thumbnails using the image_processing gem:

include ImageProcessing::MiniMagick
plugin :processing

process(:store) do |io, context|
  original = io.download

  size_800 = resize_to_limit!(original, 800, 800)
  size_500 = resize_to_limit(size_800,  500, 500)
  size_300 = resize_to_limit(size_500,  300, 300)

  {large: size_800, medium: size_500, small: size_300}
end

You probably want to load the delete_raw plugin to automatically delete processed files after they have been uploaded.

Now when you access the stored attachment through the model, a hash of uploaded files will be returned:

user.avatar_data #=>
# '{
#   "large": {"id":"lg043.jpg", "storage":"store", "metadata":{...}},
#   "medium": {"id":"kd9fk.jpg", "storage":"store", "metadata":{...}},
#   "small": {"id":"932fl.jpg", "storage":"store", "metadata":{...}}
# }'

user.avatar #=>
# {
#   :large =>  #<Shrine::UploadedFile @data={"id"=>"lg043.jpg", ...}>,
#   :medium => #<Shrine::UploadedFile @data={"id"=>"kd9fk.jpg", ...}>,
#   :small =>  #<Shrine::UploadedFile @data={"id"=>"932fl.jpg", ...}>,
# }

user.avatar[:medium]     #=> #<Shrine::UploadedFile>
user.avatar[:medium].url #=> "/uploads/store/lg043.jpg"

The plugin also extends the Attacher#url to accept versions:

user.avatar_url(:large)
user.avatar_url(:small, download: true) # with URL options

Original file

If you want to keep the original file, you can include the original Shrine::UploadedFile object as one of the versions:

process(:store) do |io, context|
  # processing thumbnail
  {original: io, thumbnail: thumbnail}
end

If both temporary and permanent storage are Amazon S3, the cached original will simply be copied over to permanent storage (without any downloading and reuploading), so in these cases the performance impact of storing the original file in addition to processed versions is neglibible.

Fallbacks

If versions are processed in a background job, there will be a period where the user will browse the site before versions have finished processing. In this period Attacher#url will by default fall back to the original file.

user.avatar #=> #<Shrine::UploadedFile>
user.avatar_url(:large) # falls back to `user.avatar_url`

This behaviour is convenient if you want to gracefully degrade to the cached file until the background job has finished processing. However, if you would rather provide your own default URLs for versions, you can disable this fallback:

plugin :versions, fallback_to_original: false

If you already have some versions processed in the foreground after a background job is kicked off (with the recache plugin), you can have URLs for versions that are yet to be processed fall back to existing versions:

plugin :versions, fallbacks: {
  :thumb_2x => :thumb,
  :large_2x => :large,
}

# ... (background job is kicked off)

user.avatar_url(:thumb_2x) # returns :thumb URL until :thumb_2x becomes available
user.avatar_url(:large_2x) # returns :large URL until :large_2x becomes available

Context

The version name will be available via :version when generating location or a default URL.

def generate_location(io, context)
  "uploads/#{context[:version]}-#{super}"
end

Attacher.default_url do |options|
  "/images/defaults/#{options[:version]}.jpg"
end

Methods

Public Class

  1. configure
  2. load_dependencies

Public Class methods

configure (uploader, opts = {})
[show source]
# File lib/shrine/plugins/versions.rb, line 119
def self.configure(uploader, opts = {})
  warn "The versions Shrine plugin doesn't need the :names option anymore, you can safely remove it." if opts.key?(:names)

  uploader.opts[:version_names] = opts.fetch(:names, uploader.opts[:version_names])
  uploader.opts[:version_fallbacks] = opts.fetch(:fallbacks, uploader.opts.fetch(:version_fallbacks, {}))
  uploader.opts[:versions_fallback_to_original] = opts.fetch(:fallback_to_original, uploader.opts.fetch(:versions_fallback_to_original, true))
end
load_dependencies (uploader, *)
[show source]
# File lib/shrine/plugins/versions.rb, line 114
def self.load_dependencies(uploader, *)
  uploader.plugin :multi_delete
  uploader.plugin :default_url
end