shrine 3.0.1 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of shrine might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/LICENSE.txt +1 -1
- data/README.md +7 -2
- data/doc/advantages.md +29 -12
- data/doc/carrierwave.md +54 -22
- data/doc/changing_derivatives.md +39 -39
- data/doc/getting_started.md +63 -58
- data/doc/multiple_files.md +5 -3
- data/doc/paperclip.md +92 -33
- data/doc/plugins/activerecord.md +1 -1
- data/doc/plugins/data_uri.md +2 -2
- data/doc/plugins/derivation_endpoint.md +26 -28
- data/doc/plugins/derivatives.md +170 -142
- data/doc/plugins/determine_mime_type.md +2 -2
- data/doc/plugins/infer_extension.md +2 -2
- data/doc/plugins/instrumentation.md +1 -1
- data/doc/plugins/metadata_attributes.md +21 -10
- data/doc/plugins/persistence.md +1 -0
- data/doc/plugins/refresh_metadata.md +5 -4
- data/doc/plugins/remote_url.md +2 -2
- data/doc/plugins/signature.md +11 -2
- data/doc/plugins/store_dimensions.md +2 -2
- data/doc/plugins/upload_endpoint.md +7 -11
- data/doc/plugins/validation_helpers.md +3 -3
- data/doc/processing.md +5 -5
- data/doc/refile.md +30 -9
- data/doc/release_notes/2.19.0.md +1 -1
- data/doc/release_notes/3.0.1.md +4 -0
- data/doc/release_notes/3.1.0.md +73 -0
- data/doc/securing_uploads.md +1 -1
- data/doc/storage/file_system.md +1 -1
- data/doc/storage/s3.md +1 -5
- data/doc/upgrading_to_3.md +4 -2
- data/doc/validation.md +3 -2
- data/lib/shrine.rb +1 -2
- data/lib/shrine/attacher.rb +4 -4
- data/lib/shrine/attachment.rb +3 -3
- data/lib/shrine/plugins/add_metadata.rb +1 -5
- data/lib/shrine/plugins/default_storage.rb +6 -6
- data/lib/shrine/plugins/derivatives.rb +4 -3
- data/lib/shrine/plugins/signature.rb +7 -6
- data/lib/shrine/plugins/store_dimensions.rb +18 -9
- data/lib/shrine/uploaded_file.rb +0 -1
- data/lib/shrine/version.rb +2 -2
- metadata +3 -2
@@ -106,7 +106,7 @@ payload:
|
|
106
106
|
|
107
107
|
A default log subscriber is added as well which logs these events:
|
108
108
|
|
109
|
-
```
|
109
|
+
```
|
110
110
|
MIME Type (33ms) – {:io=>StringIO, :uploader=>Shrine}
|
111
111
|
```
|
112
112
|
|
@@ -117,7 +117,7 @@ plugin :determine_mime_type, log_subscriber: -> (event) {
|
|
117
117
|
Shrine.logger.info JSON.generate(name: event.name, duration: event.duration, **event.payload)
|
118
118
|
}
|
119
119
|
```
|
120
|
-
```
|
120
|
+
```
|
121
121
|
{"name":"mime_type","duration":24,"io":"#<StringIO:0x00007fb7c5b08b80>","uploader":"Shrine"}
|
122
122
|
```
|
123
123
|
|
@@ -70,7 +70,7 @@ payload:
|
|
70
70
|
|
71
71
|
A default log subscriber is added as well which logs these events:
|
72
72
|
|
73
|
-
```
|
73
|
+
```
|
74
74
|
Extension (5ms) – {:mime_type=>"image/jpeg", :uploader=>Shrine}
|
75
75
|
```
|
76
76
|
|
@@ -81,7 +81,7 @@ plugin :infer_extension, log_subscriber: -> (event) {
|
|
81
81
|
Shrine.logger.info JSON.generate(name: event.name, duration: event.duration, **event.payload)
|
82
82
|
}
|
83
83
|
```
|
84
|
-
```
|
84
|
+
```
|
85
85
|
{"name":"extension","duration":5,"mime_type":"image/jpeg","uploader":"Shrine"}
|
86
86
|
```
|
87
87
|
|
@@ -34,7 +34,7 @@ uploaded_file.exists?
|
|
34
34
|
uploaded_file.download
|
35
35
|
uploaded_file.delete
|
36
36
|
```
|
37
|
-
```
|
37
|
+
```
|
38
38
|
Metadata (32ms) – {:storage=>:store, :io=>StringIO, :uploader=>Shrine}
|
39
39
|
Upload (1523ms) – {:storage=>:store, :location=>"ed0e30ddec8b97813f2c1f4cfd1700b4", :io=>StringIO, :upload_options=>{}, :uploader=>Shrine}
|
40
40
|
Exists (755ms) – {:storage=>:store, :location=>"ed0e30ddec8b97813f2c1f4cfd1700b4", :uploader=>Shrine}
|
@@ -2,21 +2,18 @@
|
|
2
2
|
title: Metadata Attributes
|
3
3
|
---
|
4
4
|
|
5
|
-
The [`metadata_attributes`][metadata_attributes] plugin allows you to
|
6
|
-
attachment metadata to additional record attributes. You can
|
7
|
-
|
8
|
-
method:
|
5
|
+
The [`metadata_attributes`][metadata_attributes] plugin allows you to write
|
6
|
+
attachment metadata to additional record attributes. You can configure the
|
7
|
+
plugin with a hash of mappings:
|
9
8
|
|
10
9
|
```rb
|
11
10
|
plugin :metadata_attributes, :size => :size, :mime_type => :type
|
12
|
-
|
13
11
|
# or
|
14
|
-
|
15
12
|
plugin :metadata_attributes
|
16
13
|
Attacher.metadata_attributes :size => :size, :mime_type => :type
|
17
14
|
```
|
18
15
|
|
19
|
-
The above configuration will
|
16
|
+
The above configuration will write `size` metadata field to `<attachment>_size`
|
20
17
|
record attribute, and `mime_type` metadata field to `<attachment>_type` record
|
21
18
|
attribute.
|
22
19
|
|
@@ -32,6 +29,18 @@ user.avatar_size #=> nil
|
|
32
29
|
user.avatar_type #=> nil
|
33
30
|
```
|
34
31
|
|
32
|
+
## Model and Entity
|
33
|
+
|
34
|
+
With the [`model`][model] plugin, any method that internally calls
|
35
|
+
`Attacher#write` will trigger metadata attributes writing (`Attacher#assign`,
|
36
|
+
`Attacher#attach`, `Attacher#change`, `Attacher#set`).
|
37
|
+
|
38
|
+
```rb
|
39
|
+
attacher.file.metadata["mime_type"] = "other/type"
|
40
|
+
attacher.write
|
41
|
+
attacher.record.avatar_type #=> "other/type"
|
42
|
+
```
|
43
|
+
|
35
44
|
If you're using the [`entity`][entity] plugin, metadata attributes will be
|
36
45
|
added to `Attacher#column_values`:
|
37
46
|
|
@@ -45,6 +54,11 @@ attacher.column_values #=>
|
|
45
54
|
# }
|
46
55
|
```
|
47
56
|
|
57
|
+
Any metadata attributes that were declared but are missing on the record will
|
58
|
+
be skipped.
|
59
|
+
|
60
|
+
## Full attribute name
|
61
|
+
|
48
62
|
If you want to specify the full record attribute name, pass the record
|
49
63
|
attribute name as a string instead of a symbol.
|
50
64
|
|
@@ -56,8 +70,5 @@ photo.image = image
|
|
56
70
|
photo.original_filename #=> "nature.jpg"
|
57
71
|
```
|
58
72
|
|
59
|
-
Any metadata attributes that were declared but are missing on the record will
|
60
|
-
be skipped.
|
61
|
-
|
62
73
|
[metadata_attributes]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/metadata_attributes.rb
|
63
74
|
[entity]: https://shrinerb.com/docs/plugins/entity
|
data/doc/plugins/persistence.md
CHANGED
@@ -12,17 +12,18 @@ plugin :refresh_metadata
|
|
12
12
|
It provides `#refresh_metadata!` method, which triggers metadata extraction
|
13
13
|
(calls `Shrine#extract_metadata`) with the uploaded file opened for reading,
|
14
14
|
and updates the existing metadata hash with the results. This can be done
|
15
|
-
on the
|
15
|
+
on the `Shrine::Attacher` or the `Shrine::UploadedFile` level.
|
16
16
|
|
17
17
|
## Attacher
|
18
18
|
|
19
19
|
Calling `#refresh_metadata!` on a `Shrine::Attacher` object will re-extract
|
20
|
-
metadata of the attached file
|
21
|
-
data back into the attachment attribute.
|
20
|
+
metadata of the attached file, and when used with a [model], it will write new
|
21
|
+
file data back into the attachment attribute.
|
22
22
|
|
23
23
|
```rb
|
24
24
|
attacher.refresh_metadata!
|
25
|
-
attacher.file.metadata
|
25
|
+
attacher.file.metadata # re-extracted metadata
|
26
|
+
attacher.record.file_data #=> '{ ... data with updated metadata ... }'
|
26
27
|
```
|
27
28
|
|
28
29
|
The `Attacher#context` hash will be forwarded to metadata extraction, as well
|
data/doc/plugins/remote_url.md
CHANGED
@@ -166,7 +166,7 @@ following payload:
|
|
166
166
|
|
167
167
|
A default log subscriber is added as well which logs these events:
|
168
168
|
|
169
|
-
```
|
169
|
+
```
|
170
170
|
Remote URL (1550ms) – {:remote_url=>"https://example.com/image.jpg",:download_options=>{},:uploader=>Shrine}
|
171
171
|
```
|
172
172
|
|
@@ -177,7 +177,7 @@ plugin :remote_url, log_subscriber: -> (event) {
|
|
177
177
|
Shrine.logger.info JSON.generate(name: event.name, duration: event.duration, **event.payload)
|
178
178
|
}
|
179
179
|
```
|
180
|
-
```
|
180
|
+
```
|
181
181
|
{"name":"remote_url","duration":5,"remote_url":"https://example.com/image.jpg","download_options":{},"uploader":"Shrine"}
|
182
182
|
```
|
183
183
|
|
data/doc/plugins/signature.md
CHANGED
@@ -55,6 +55,15 @@ add_metadata :md5 do |io, action: nil, **|
|
|
55
55
|
end
|
56
56
|
```
|
57
57
|
|
58
|
+
## Rewinding
|
59
|
+
|
60
|
+
If you want to calculate signature from a non-rewindable IO object, you can
|
61
|
+
tell Shrine to skip rewinding:
|
62
|
+
|
63
|
+
```rb
|
64
|
+
Shrine.calculate_signature(io, :md5, rewind: false)
|
65
|
+
```
|
66
|
+
|
58
67
|
## Instrumentation
|
59
68
|
|
60
69
|
If the `instrumentation` plugin has been loaded, the `signature` plugin adds
|
@@ -76,7 +85,7 @@ following payload:
|
|
76
85
|
|
77
86
|
A default log subscriber is added as well which logs these events:
|
78
87
|
|
79
|
-
```
|
88
|
+
```
|
80
89
|
MIME Type (33ms) – {:io=>StringIO, :uploader=>Shrine}
|
81
90
|
```
|
82
91
|
|
@@ -87,7 +96,7 @@ plugin :signature, log_subscriber: -> (event) {
|
|
87
96
|
Shrine.logger.info JSON.generate(name: event.name, duration: event.duration, **event.payload)
|
88
97
|
}
|
89
98
|
```
|
90
|
-
```
|
99
|
+
```
|
91
100
|
{"name":"signature","duration":24,"io":"#<StringIO:0x00007fb7c5b08b80>","uploader":"Shrine"}
|
92
101
|
```
|
93
102
|
|
@@ -110,7 +110,7 @@ following payload:
|
|
110
110
|
|
111
111
|
A default log subscriber is added as well which logs these events:
|
112
112
|
|
113
|
-
```
|
113
|
+
```
|
114
114
|
Image Dimensions (108ms) – {:io=>File, :uploader=>Shrine}
|
115
115
|
```
|
116
116
|
|
@@ -121,7 +121,7 @@ plugin :store_dimensions, log_subscriber: -> (event) {
|
|
121
121
|
Shrine.logger.info JSON.generate(name: event.name, duration: event.duration, **event.payload)
|
122
122
|
}
|
123
123
|
```
|
124
|
-
```
|
124
|
+
```
|
125
125
|
{"name":"image_dimensions","duration":114,"io":"#<File:0x00007fc445371d90>","uploader":"Shrine"}
|
126
126
|
```
|
127
127
|
|
@@ -95,16 +95,9 @@ plugin :upload_endpoint, max_size: 20*1024*1024 # 20 MB
|
|
95
95
|
If the uploaded file is larger than the specified value, a `413 Payload Too
|
96
96
|
Large` response will be returned.
|
97
97
|
|
98
|
-
##
|
98
|
+
## Uploader options
|
99
99
|
|
100
|
-
|
101
|
-
upload happens independently of a database record. The endpoint will send the
|
102
|
-
following upload context:
|
103
|
-
|
104
|
-
* `:action` – holds the value `:upload`
|
105
|
-
* `:request` – holds an instance of `Rack::Request`
|
106
|
-
|
107
|
-
You can update the upload context via `:upload_context`:
|
100
|
+
You can pass additional uploader options via `:upload_context`:
|
108
101
|
|
109
102
|
```rb
|
110
103
|
plugin :upload_endpoint, upload_context: -> (request) do
|
@@ -112,13 +105,16 @@ plugin :upload_endpoint, upload_context: -> (request) do
|
|
112
105
|
end
|
113
106
|
```
|
114
107
|
|
108
|
+
Note that the uploader will *not* receive `:record` and `:name` values, as the
|
109
|
+
upload happens independently of a database record.
|
110
|
+
|
115
111
|
## Upload
|
116
112
|
|
117
113
|
You can also customize the upload itself via the `:upload` option:
|
118
114
|
|
119
115
|
```rb
|
120
|
-
plugin :upload_endpoint, upload: -> (io,
|
121
|
-
Shrine.upload(io, :cache,
|
116
|
+
plugin :upload_endpoint, upload: -> (io, **options, request) do
|
117
|
+
Shrine.upload(io, :cache, **options)
|
122
118
|
end
|
123
119
|
```
|
124
120
|
|
@@ -150,11 +150,11 @@ the `:default_messages` option to the plugin:
|
|
150
150
|
```rb
|
151
151
|
plugin :validation_helpers, default_messages: {
|
152
152
|
max_size: -> (max) { I18n.t("errors.file.max_size", max: max) },
|
153
|
-
min_size: -> (
|
153
|
+
min_size: -> (min) { I18n.t("errors.file.min_size", min: min) },
|
154
154
|
max_width: -> (max) { I18n.t("errors.file.max_width", max: max) },
|
155
|
-
min_width: -> (
|
155
|
+
min_width: -> (min) { I18n.t("errors.file.min_width", min: min) },
|
156
156
|
max_height: -> (max) { I18n.t("errors.file.max_height", max: max) },
|
157
|
-
min_height: -> (
|
157
|
+
min_height: -> (min) { I18n.t("errors.file.min_height", min: min) },
|
158
158
|
max_dimensions: -> (dims) { I18n.t("errors.file.max_dimensions", dims: dims) },
|
159
159
|
min_dimensions: -> (dims) { I18n.t("errors.file.min_dimensions", dims: dims) },
|
160
160
|
mime_type_inclusion: -> (list) { I18n.t("errors.file.mime_type_inclusion", list: list) },
|
data/doc/processing.md
CHANGED
@@ -13,7 +13,7 @@ processing with [ImageMagick]/[GraphicsMagick] (using the [MiniMagick] gem) or
|
|
13
13
|
[libvips] (using the [ruby-vips] gem; see the [libvips section](#libvips)).
|
14
14
|
Here is an example of generating a thumbnail with ImageProcessing:
|
15
15
|
|
16
|
-
```
|
16
|
+
```
|
17
17
|
$ brew install imagemagick
|
18
18
|
```
|
19
19
|
```rb
|
@@ -43,7 +43,7 @@ Shrine.plugin :derivatives
|
|
43
43
|
require "image_processing/mini_magick"
|
44
44
|
|
45
45
|
class ImageUploader < Shrine
|
46
|
-
Attacher.
|
46
|
+
Attacher.derivatives do |original|
|
47
47
|
magick = ImageProcessing::MiniMagick.source(original)
|
48
48
|
|
49
49
|
{
|
@@ -163,7 +163,7 @@ class ImageUploader < Shrine
|
|
163
163
|
small: [300, 300],
|
164
164
|
}
|
165
165
|
|
166
|
-
Attacher.
|
166
|
+
Attacher.derivatives do |original, name:|
|
167
167
|
thumbnail = ImageProcessing::MiniMagick
|
168
168
|
.source(original)
|
169
169
|
.resize_to_limit!(*THUMBNAILS.fetch(name))
|
@@ -223,7 +223,7 @@ gem "streamio-ffmpeg"
|
|
223
223
|
require "streamio-ffmpeg"
|
224
224
|
|
225
225
|
class VideoUploader < Shrine
|
226
|
-
Attacher.
|
226
|
+
Attacher.derivatives do |original|
|
227
227
|
transcoded = Tempfile.new ["transcoded", ".mp4"]
|
228
228
|
screenshot = Tempfile.new ["screenshot", ".jpg"]
|
229
229
|
|
@@ -306,7 +306,7 @@ low memory usage (see [Why is libvips quick]).
|
|
306
306
|
Using libvips is as easy as installing it and switching to the
|
307
307
|
`ImageProcessing::Vips` backend:
|
308
308
|
|
309
|
-
```
|
309
|
+
```
|
310
310
|
$ brew install vips
|
311
311
|
```
|
312
312
|
|
data/doc/refile.md
CHANGED
@@ -6,7 +6,7 @@ This guide is aimed at helping Refile users transition to Shrine, and it consist
|
|
6
6
|
of three parts:
|
7
7
|
|
8
8
|
1. Explanation of the key differences in design between Refile and Shrine
|
9
|
-
2. Instructions how to migrate
|
9
|
+
2. Instructions how to migrate an existing app that uses Refile to Shrine
|
10
10
|
3. Extensive reference of Refile's interface with Shrine equivalents
|
11
11
|
|
12
12
|
## Overview
|
@@ -199,13 +199,18 @@ explains this setup in more detail.
|
|
199
199
|
## Migrating from Refile
|
200
200
|
|
201
201
|
You have an existing app using Refile and you want to transfer it to
|
202
|
-
Shrine. Let's assume we have a `Photo` model with the "image" attachment.
|
203
|
-
|
202
|
+
Shrine. Let's assume we have a `Photo` model with the "image" attachment.
|
203
|
+
|
204
|
+
### 1. Add Shrine column
|
205
|
+
|
206
|
+
First we need to create the `image_data` column for Shrine:
|
204
207
|
|
205
208
|
```rb
|
206
209
|
add_column :photos, :image_data, :text
|
207
210
|
```
|
208
211
|
|
212
|
+
### 2. Dual write
|
213
|
+
|
209
214
|
Afterwards we need to make new uploads write to the `image_data` column. This
|
210
215
|
can be done by including the below module to all models that have Refile
|
211
216
|
attachments:
|
@@ -219,8 +224,7 @@ Shrine.storages = {
|
|
219
224
|
}
|
220
225
|
|
221
226
|
Shrine.plugin :model
|
222
|
-
|
223
|
-
```rb
|
227
|
+
|
224
228
|
module RefileShrineSynchronization
|
225
229
|
def write_shrine_data(name)
|
226
230
|
attacher = Shrine::Attacher.from_model(self, name)
|
@@ -257,8 +261,12 @@ end
|
|
257
261
|
```
|
258
262
|
|
259
263
|
After you deploy this code, the `image_data` column should now be successfully
|
260
|
-
synchronized with new attachments.
|
261
|
-
|
264
|
+
synchronized with new attachments.
|
265
|
+
|
266
|
+
### 3. Data migration
|
267
|
+
|
268
|
+
Next step is to run a script which writes all existing Refile attachments to
|
269
|
+
`image_data`:
|
262
270
|
|
263
271
|
```rb
|
264
272
|
Photo.find_each do |photo|
|
@@ -267,9 +275,22 @@ Photo.find_each do |photo|
|
|
267
275
|
end
|
268
276
|
```
|
269
277
|
|
278
|
+
### 4. Rewrite code
|
279
|
+
|
270
280
|
Now you should be able to rewrite your application so that it uses Shrine
|
271
|
-
instead of Refile
|
272
|
-
the
|
281
|
+
instead of Refile (you can consult the reference in the next section). You can
|
282
|
+
remove the `RefileShrineSynchronization` module as well.
|
283
|
+
|
284
|
+
### 5. Remove Refile columns
|
285
|
+
|
286
|
+
If everything is looking good, we can remove Refile columns:
|
287
|
+
|
288
|
+
```rb
|
289
|
+
remove_column :photos, :image_id
|
290
|
+
remove_column :photos, :image_size
|
291
|
+
remove_column :photos, :image_filename
|
292
|
+
remove_column :photos, :image_content_type
|
293
|
+
```
|
273
294
|
|
274
295
|
## Refile to Shrine direct mapping
|
275
296
|
|
data/doc/release_notes/2.19.0.md
CHANGED
@@ -16,7 +16,7 @@ title: Shrine 2.19.0
|
|
16
16
|
uploaded_file.download
|
17
17
|
uploaded_file.delete
|
18
18
|
```
|
19
|
-
```
|
19
|
+
```
|
20
20
|
Metadata (32ms) – {:storage=>:store, :io=>StringIO, :uploader=>Shrine}
|
21
21
|
Upload (1523ms) – {:storage=>:store, :location=>"ed0e30ddec8b97813f2c1f4cfd1700b4", :io=>StringIO, :upload_options=>{}, :uploader=>Shrine}
|
22
22
|
Exists (755ms) – {:storage=>:store, :location=>"ed0e30ddec8b97813f2c1f4cfd1700b4", :uploader=>Shrine}
|
data/doc/release_notes/3.0.1.md
CHANGED
@@ -0,0 +1,73 @@
|
|
1
|
+
---
|
2
|
+
title: Shrine 3.1.0
|
3
|
+
---
|
4
|
+
|
5
|
+
## New features
|
6
|
+
|
7
|
+
* The `Attacher#create_derivatives` method now accepts a `:storage` option for
|
8
|
+
specifying the storage to which derivatives should be uploaded.
|
9
|
+
|
10
|
+
```rb
|
11
|
+
# with attachment module
|
12
|
+
photo.image_derivatives!(storage: :other_store)
|
13
|
+
|
14
|
+
# with attacher
|
15
|
+
attacher.create_derivatives(storage: :other_store)
|
16
|
+
```
|
17
|
+
|
18
|
+
* The `Shrine.calculate_signature` now accepts a `:rewind` boolean option for
|
19
|
+
choosing whether the IO object should be rewinded after reading. This is
|
20
|
+
useful if you want to calculate signature from non-rewindable IO objects,
|
21
|
+
such as `IO.pipe`, `Socket`, non-rewindable `Down::ChunkedIO` etc.
|
22
|
+
|
23
|
+
```rb
|
24
|
+
Shrine.signature(io, rewind: false)
|
25
|
+
```
|
26
|
+
|
27
|
+
## Improvements
|
28
|
+
|
29
|
+
* The derivatives processor can now be registered with `Attacher.derivatives`,
|
30
|
+
which is just an alias for `Attacher.derivatives_processor`.
|
31
|
+
|
32
|
+
```rb
|
33
|
+
class ImageUploader < Shrine
|
34
|
+
Attacher.derivatives_processor do |original|
|
35
|
+
# ...
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# can now be written as
|
40
|
+
|
41
|
+
class ImageUploader < Shrine
|
42
|
+
Attacher.derivatives do |original|
|
43
|
+
# ...
|
44
|
+
end
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
* The `Attacher#cached?` and `Attacher#stored?` methods now work correctly if
|
49
|
+
temporary/permanent storage identifiers were specified as strings.
|
50
|
+
|
51
|
+
* The `store_dimensions` plugin now properly propagates exceptions when loading
|
52
|
+
the `ruby-vips` gem in `:vips` analyzer.
|
53
|
+
|
54
|
+
* The `add_metadata` plugin now respects inheritance again when defining
|
55
|
+
metadata methods on the `Shrine::UploadedFile` class. In 2.19.0, the
|
56
|
+
`add_metadata` plugin was changed to define metadata methods on the internal
|
57
|
+
`FileMethods` plugin module, which is shared across all uploaders. This
|
58
|
+
change has now been reverted.
|
59
|
+
|
60
|
+
## Backwards compatibility
|
61
|
+
|
62
|
+
* The `Attacher#cache_key` and `Attacher#store_key` methods now always return
|
63
|
+
symbol keys, even if the storage key that was specified was a string key.
|
64
|
+
|
65
|
+
```rb
|
66
|
+
attacher = Shrine::Attacher.new(cache: "cache", store: "store")
|
67
|
+
attacher.cache_key #=> :cache (previously "cache")
|
68
|
+
attacher.store_key #=> :store (previously "store")
|
69
|
+
```
|
70
|
+
|
71
|
+
* The `add_metadata` plugin now defines metadata methods directly on the
|
72
|
+
`UploadedFile` class, which means that if you happen to have been overriding
|
73
|
+
these metadata methods and calling `super`, this won't work anymore.
|