---
title: Shrine 2.6.0
---

## New plugins

* Added `signature` plugin which allows you to calculate a
  SHA{1,256,384,512}/MD5/CRC32 hash of a file, in raw, hex or base64 encoding.

```rb
Shrine.plugin :signature

Shrine.calculate_signature(io, :md5)
#=> "8c7dd922ad47494fc02c388e12c00eac"

Shrine.calculate_signature(io, :md5, format: :base64)
#=> "jH3ZIq1HSU/ALDiOEsAOrA==\n"
```

  You can then easily create a new metadata field with the calculated hash:

```rb
Shrine.plugin :signature
Shrine.plugin :add_metadata

MyUploader.add_metadata :md5 do |io, context|
  calculate_signature(io, :md5)
end
```

* Added `metadata_attibutes` plugin which allows you to sync attachment
  metadata to additional record attributes.

```rb
Shrine.plugin :metadata_attributes

# Syncs `size` metadata to `#<attachment>_size` record attribute, and
# `mime_type` metadata to `#<attachment>_type` record attribute.
Shrine::Attacher.metadata_attributes :size => :size, :mime_type => :type

# ...

user.avatar = image
user.avatar.metadata["size"]      #=> 95724
user.avatar_size                  #=> 95724
user.avatar.metadata["mime_type"] #=> "image/jpeg"
user.avatar_type                  #=> "image/jpeg"

user.avatar = nil
user.avatar_size #=> nil
user.avatar_type #=> nil
```

* Added `refresh_metadata` plugin (extracted from the `restore_cached_data`
  plugin) which allows you to re-extract metadata from an uploaded file.

```rb
Shrine.plugin :refresh_metadata

# ...

uploaded_file.refresh_metadata!
uploaded_file.metadata # re-extracted metadata
```

## New features

* Added `Shrine.determine_mime_type` and `Shrine.mime_type_analyzers` methods
  to `determine_mime_type` plugin for extracting MIME type from a file.

```rb
Shrine.plugin :determine_mime_type

Shrine.determine_mime_type(io) # calls the defined analyzer
#=> "image/jpeg"

Shrine.mime_type_analyzers[:file].call(io) # calls a built-in analyzer
#=> "image/jpeg"
```

* Added `Shrine.extract_dimensions` and `Shrine.dimensions_analyzers` methods
  to `store_dimensions` plugin for extracting dimensions from a file.

```rb
Shrine.plugin :store_dimensions

Shrine.extract_dimensions(io) # calls the defined analyzer
#=> [300, 400]

Shrine.dimensions_analyzers[:fastimage].call(io) # calls a built-in analyzer
#=> [300, 400]
```

* Added `Shrine.data_uri` method to `data_uri` plugin for converting a data URI
  into an IO object.

```rb
Shrine.plugin :data_uri

io = Shrine.data_uri("data:image/png;base64,9kfg07a80ihtiort87t85")
io.content_type #=> "image/png"
io.size         #=> 482
```

* Added `Shrine.rack_file` method to `rack_file` plugin for converting the Rack
  uploaded file hash into an IO object.

```rb
Shrine.plugin :rack_file

file_hash #=>
# {
#   :name => "file",
#   :filename => "cats.png",
#   :type => "image/png",
#   :tempfile => #<Tempfile:/var/folders/3n/3asd/-Tmp-/RackMultipart201-1476-nfw2-0>,
#   :head => "Content-Disposition: form-data; ...",
# }

io = Shrine.rack_file(file_hash)
io.original_filename #=> "cats.png"
io.content_type      #=> "image/png"
io.size              #=> 58342
```

## Performance improvements

* Improved performance of parsing data URIs up to 10x by switching from regex
  matching to `StringScanner`, and the intermediary base64-encoded content
  string is now deallocated after it's decoded.

* `UploadedFile#base64` now deallocates the intermediary binary content string
  after converting it to base64 format in `data_uri` plugin.

* The default multipart copy threshold for `Shrine::Storage::S3` has been
  bumped from 15MB to 100MB, which is about the size where parallelized
  multipart copy starts being faster.

* Uploading files from `FileSystem` storage to `S3` storage will now utilize
  aws-sdk's parallelized multipart upload on files with 15MB or above, which is
  the scenario when your temporary storage is `FileSystem` and permanent
  storage is `S3`.

* `Shrine::Storage::S3#download` now uses only one file descriptor.

* The `logging` plugin doesn't require the `benchmark` standard library anymore,
  which reduces the memory footprint.

## Other improvements

* Fixed wrong implementation of `FileSystem#clear!(older_than:
  expiration_date)`, where in common scenarios it wouldn't delete old files, or
  it would incorrectly delete files which still didn't pass the expiration
  date.

* The `delete_raw` plugin now deletes any uploaded IO objects that respond to
  `#path`, not just `Tempfile` objects (this includes `File`,
  `ActionDispatch::Http::UploadedFile`, and
  `Shrine::Plugins::RackFile::UploadedFile` objects).

* The `rack_file` plugin now works with Grape.

* The `data_uri` plugin now accepts URI-encoded raw data URIs.

* The `data_uri` plugin now accepts data URIs with additional media type params.

* `Shrine::Storage::S3` now accepts separate multipart thresholds for uploading
  and for copying.

* `Shrine::Storage::S3#object` is now public, which returns an `Aws::S3::Object`
  representing the file.

```rb
s3.object("image.jpg") #=> #<Aws::S3::Object bucket_name="your-bucket" key="image.jpg">
```

* Added `Shrine::Storage::S3#client` method for quicker access to the
  `Aws::S3::Client` instance.

* The "S3" component of the `aws-sdk` gem is now eagerly loaded in
  `lib/shrine/storage/s3.rb`, to remove possibility of autoloading causing
  errors in multi-threaded systems.

* `Shrine::Storage::FileSystem#path` is now public, which returns a `Pathname`
  to the file.

```rb
filesystem.path("image.jpg") #=> #<Pathname:public/image.jpg>
```

* Shrine now checks whether `Shrine#generate_location` happened to return nil,
  and raises `Shrine::Error`.

* `Attacher#finalize` can now be called even when the attachment hasn't changed.

* Added `Attacher#changed?` alias to `Attacher#attached?`.

* The logic for rejecting attachments that are already the current attachment
  has been moved from `Attacher#assign` to `Attacher#set`.

* The `remove_invalid` plugin will now only remove new invalid attachments.

* The `tempfile` standard library is now correctly required in `lib/shrine.rb`.

* Improved default validation error messages in `validation_helpers` plugin.

* Blacklisted MIME types and extensions are now excluded from the default error
  message for security reasons.

* The `add_metadata` plugin now also accepts hashes with symbol keys.

* The loaded plugin module is now returned when calling `Shrine.plugin`.

* Improved visibility of Shrine deprecation warnings.

## Backwards compatibility

* Passing regexes to `validate_(mime_type|extension)_(inclusion|exclusion)` has
  been deprecated due to lack of usefulness and for security reasons, from now
  on you should always pass plain strings.

```rb
# deprecated
validate_mime_type_inclusion [/image\//]
validate_extension_inclusion [/jpe?g/]

# use strings instead
validate_mime_type_inclusion %w[image/jpeg image/png image/gif ...]
validate_extension_inclusion %w[jpg jpeg png gif ...]
```

* Previously the `validate_(max|min)_(width|height)` validations would ignore
  `width` or `height` being nil, but this is now deprecated and in Shrine 3
  this will return an error. You should make sure that the file is of the right
  type before validating dimensions.

```rb
if validate_mime_type_inclusion %w[image/jpeg image/png image/gif]
  validate_max_width 1000
  validate_max_height 1000
end
```

* Passing a Rack uploaded file hash to `Shrine#upload` and `Shrine#store` is
  now deprecated in `rack_file` plugin, use `Shrine.rack_file` to first convert
  the Rack hash into an IO object.

* Deprecated passing `:multipart_threshold` option as an integer in
  `Shrine::Storage::S3`, use a hash with `:upload` and `:copy` keys.

* Deprecated `Shrine::Storage::S3#s3` in favour of
  `Shrine::Storage::S3#client`.

* The `Shrine::Plugins::DataUri::DataFile` isn't a subclass of `StringIO`
  anymore, instead it uses composition to delegate only a subset of IO methods
  to the underlying `StringIO` object. This shouldn't cause any backwards
  compatibility unless the user was relying on it to be a subclass of
  `StringIO`.
