---
title: Shrine 2.15.0
---

## New features

* The [`derivation_endpoint`][derivation_endpoint] plugin has been added, which
  provides on-the-fly processing functionality, similar to what Dragonfly,
  Refile, and Active Storage provide. It's suitable for fast transformations,
  such as generating image thumbnails or document previews.

  Rather than encoding processing steps in the URL (like Dragonfly and Active
  Storage do), with `derivation_endpoint` you generate URLs to named
  "derivation" blocks, passing any arguments you need for the processing.

  ```rb
  photo.image.derivation_url(:thumbnail, 600, 400)
  #=> "derivations/image/thumbnail/600/400/eyJpZCI6ImZvbyIsInN0b3JhZ2UiOiJzdG9yZSJ9?signature=..."
  ```

  When the URL is requested, it's routed to a Rack app that you mount in your
  router, which knows how to resolve the HTTP request, call the appropriate
  processing, and generate an HTTP response.

  ```rb
  # config/routes.rb (Rails)
  Rails.application.routes.draw do
    mount ImageUploader.derivation_endpoint => "derivations/images"
  end
  ```

  In this case the endpoint will call the `:thumbnail` derivation block defined
  in our uploader, passing it the source file and derivation arguments (in this
  case thumbnail dimensions). We can then generate the thumbnail inside the
  block:

  ```rb
  require "image_processing/mini_magick"

  class ImageUploader < Shrine
    derivation :thumbnail do |file, width, height|
      ImageProcessing::MiniMagick
        .source(file)
        .resize_to_limit!(width.to_i, height.to_i)
    end
  end
  ```

  The derivation URLs are signed with the secret key provided when loading the
  plugin, to prevent tampering and potential DoS attacks.

  ```rb
  plugin :derivation_endpoint, secret_key: "<YOUR SECRET KEY>"
  ```

  The `derivation_endpoint` plugin is highly configurable, you can set a [CDN
  host], change response headers of derivatives ([`Content-Type`],
  [`Content-Disposition`]), add [URL expiration], [cache][uploading]
  generated derivatives to a Shrine storage and more. Check out the
  [documentation][derivation_endpoint] for more details.

## Other improvements

* The `:marcel` MIME type analyzer in `determine_mime_type` plugin now uses the
  file extension to more accurately determine the correct MIME type.

* The `tempfile` plugin modifies `Shrine.with_file` to return the cached
  downloaded file for the same `Shrine::UploadedFile` object (instead of
  copying to a new file each time). However, because the same file object was
  returned, using `Shrine.with_file` wasn't thread safe. This is now fixed by
  returning a different File object on each invocation (but still pointing to
  the same file on disk).

## Backwards compatibility

* The `Shrine.download_endpoint` call provided by the `download_endpoint`
  plugin now returns a new Rack app object each time it's called. If you were
  relying on multiple invocations returning the same object, you will need to
  modify your code.

[derivation_endpoint]: https://shrinerb.com/docs/plugins/derivation_endpoint
[CDN host]: https://shrinerb.com/docs/plugins/derivation_endpoint#host
[`Content-Type`]: https://shrinerb.com/docs/plugins/derivation_endpoint#content-type
[`Content-Disposition`]: https://shrinerb.com/docs/plugins/derivation_endpoint#content-disposition
[URL expiration]: https://shrinerb.com/docs/plugins/derivation_endpoint#expiration
[uploading]: https://shrinerb.com/docs/plugins/derivation_endpoint#uploading
