---
title: Shrine 2.18.0
---

## New features

* Added `Shrine.upload_response` to `upload_endpoint` plugin for handling
  uploads inside a custom controller. This allows authenticating uploads on the
  controller level:

  ```rb
  # config/routes.rb (Rails)
  Rails.application.routes.draw do
    # ...
    post "/images/upload" => "uploads#image"
  end
  ```
  ```rb
  # app/controllers/uploads_controller.rb (Rails)
  class UploadsController < ApplicationController
    def image
      authenticate_user!

      set_rack_response ImageUploader.upload_response(:cache, request.env)
    end

    private

    def set_rack_response((status, headers, body))
      self.status = status
      self.headers.merge!(headers)
      self.response_body = body
    end
  end
  ```

* Added `Shrine.presign_response` to `presign_endpoint` plugin for handling
  uploads inside a custom controller. This allows authenticating uploads on the
  controller level:

  ```rb
  # config/routes.rb (Rails)
  Rails.application.routes.draw do
    # ...
    post "/images/presign", to: "presigns#image"
  end
  ```
  ```rb
  # app/controllers/presigns_controller.rb (Rails)
  class PresignsController < ApplicationController
    def image
      authenticate_user!

      set_rack_response ImageUploader.presign_response(:cache, request.env)
    end

    private

    def set_rack_response((status, headers, body))
      self.status = status
      self.headers.merge!(headers)
      self.response_body = body
    end
  end
  ```

* The `:url` option has been added to the `upload_endpoint` plugin for
  returning the uploaded file URL in the response.

  ```rb
  plugin :upload_endpoint, url: true
  # or
  plugin :upload_endpoint, url: { public: true }
  # or
  plugin :upload_endpoint, url: -> (uploaded_file, request) {
    uploaded_file.url(**options)
  }
  ```
  ```rb
  {
    "data": { "id": "...", "storage": "...", "metadata": {...} },
    "url": "https://example.com/path/to/file"
  }
  ```

  This will additionally be recognized by Uppy, so e.g. the Dashboard plugin
  will display preview link to the file.

  ```js
  uppy.on('upload-success', (file, response) => {
    response.uploadURL // => "https://example.com/path/to/file"
  })
  ```

## Other improvements

* The `upload_endpoint` now accepts the `files[]` array that Uppy's XHR Upload
  plugin sends by default. This means the `fieldName` parameter can now be
  omitted.

  ```js
  // BEFORE
  uppy.use(Uppy.XHRUpload, {
    endpoint: '/upload',
    fieldName: 'file',
  })

  // AFTER
  uppy.use(Uppy.XHRUpload, {
    endpoint: '/upload',
  })
  ```

* The `Shrine.upload` convenience method has been added, which is a bit shorter
  when you don't need the uploader instance.

  ```rb
  Shrine.upload(io, :storage)

  # expands to

  uploader = Shrine.new(:storage)
  uploader.upload(io)
  ```

* The `Shrine.Attachment(...)` shorthand for `Shrine::Attachment.new(...)` has
  been added.

  ```rb
  class Photo
    include Shrine::Attachment(:image) # expands to Shrine::Attachment.new(:image)
  end
  ```

* The `parsed_json` and `rack_file` plugins now correctly retain the second
  argument in the `Attacher#assign` method signature.

## Backwards compatibility

* The `aws-sdk-s3` version lower than `1.14.0` has been deprecated for
  `Shrine::Storage::S3` and will be removed in Shrine 3.

* The `:download` option in `Shrine::Storage::S3#url` has been deprecated and
  will be removed in Shrine 3. The `:response_content_disposition` option
  should be used instead.

  ```rb
  # This is deprecated:
  uploaded_file.url(download: true)

  # Use this:
  uploaded_file.url(response_content_disposition: "attachment")
  ```

* `Shrine::Storage::S3#upload` doesn't backfill the `size` metadata value for
  input IOs with unknown size (e.g. pipes, sockets). This behaviour was not
  documented and added unnecessary complexity. Moreover, this functionality
  should be storage agnostic, so if someone requests it we can add it back in
  form of a plugin.
