---
title: Shrine 3.7.0
---

## New features

* The `download_endpoint` plugin now supports expiring URLs. Configure a `secret_key` and optionally a default `expires_in` on the plugin, then pass `expires_in:` when generating a URL. The URL is signed with HMAC-SHA256, and the endpoint will reject requests with an expired or tampered signature.

  ```rb
  plugin :download_endpoint,
    prefix: "downloads",
    secret_key: "<your-secret-key>",
    expires_in: 5 * 60 # optional default; can be overridden per URL
  ```

  ```rb
  uploaded_file.download_url                      # uses the default expires_in
  uploaded_file.download_url(expires_in: 10 * 60) # override per URL
  # => "https://example.com/downloads/<token>?signature=...&expires_at=..."
  ```

* The `derivatives` plugin now accepts a `:keep_derivatives` option. When set to `true`, existing derivatives are kept when a new file is attached via `Attacher#change`, instead of being cleared.

  ```rb
  plugin :derivatives, keep_derivatives: true
  ```

  ```rb
  attacher.derivatives #=> { thumb: #<Shrine::UploadedFile> }
  attacher.change(new_file)
  attacher.derivatives #=> { thumb: #<Shrine::UploadedFile> } # preserved
  ```

* The `refresh_metadata` plugin now accepts a `replace:` keyword argument on `refresh_metadata!`. Passing `replace: true` replaces the file's metadata entirely with the freshly extracted values, instead of merging them. This is useful when you want to remove stale custom metadata keys.

  ```rb
  uploaded_file.metadata["custom"] = "stale value"

  uploaded_file.refresh_metadata!              # merge (default)
  uploaded_file.metadata["custom"]             #=> "stale value" (preserved)

  uploaded_file.refresh_metadata!(replace: true)  # replace
  uploaded_file.metadata["custom"]             #=> nil (removed)
  ```

## Other improvements

* The `s3` storage now prefers using `TransferManager#upload_stream` over the deprecated `#upload_stream` method on the S3 object, when `TransferManager` is available. This avoids deprecation warnings from newer versions of the AWS SDK.

* The `column` plugin no longer attempts to deserialize an empty string as JSON. Previously this would raise a parse error; now the attachment is treated as blank.

* The `backgrounding` plugin now correctly forwards keyword arguments passed to `Attacher#promote_cached` into the `promote_block` callback.

  ```rb
  Shrine::Attacher.promote_block do |attacher:, my_option:, **|
    # my_option was previously not forwarded here
    SomePromoteJob.perform_async(attacher.dump, my_option: my_option)
  end

  attacher.promote_cached(my_option: "value") # now forwarded correctly
  ```

* `UploadedFile` no longer produces URI default parser warnings (`URI::RFC3986_PARSER.make_regexp is obsolete`) when verbose warnings are enabled.

## Backwards compatibility

* Support for Ruby versions below 3.2 has been dropped. Ruby >= 3.2 is now required.

* ImageProcessing 2.0 made `mini_magick` and `ruby-vips` soft dependencies that are no longer loaded automatically. If you use either gem for image processing, you will need to add it explicitly to your `Gemfile`:

  ```rb
  gem "mini_magick"
  # or
  gem "ruby-vips"
  ```
