shrine 3.0.0.beta2 → 3.0.0.beta3
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 +45 -1
- data/README.md +100 -106
- data/doc/advantages.md +90 -88
- data/doc/attacher.md +322 -152
- data/doc/carrierwave.md +105 -113
- data/doc/changing_derivatives.md +308 -0
- data/doc/changing_location.md +92 -21
- data/doc/changing_storage.md +107 -0
- data/doc/creating_plugins.md +1 -1
- data/doc/design.md +8 -9
- data/doc/direct_s3.md +3 -2
- data/doc/metadata.md +97 -78
- data/doc/multiple_files.md +3 -3
- data/doc/paperclip.md +89 -88
- data/doc/plugins/activerecord.md +3 -12
- data/doc/plugins/backgrounding.md +126 -100
- data/doc/plugins/derivation_endpoint.md +4 -5
- data/doc/plugins/derivatives.md +63 -32
- data/doc/plugins/download_endpoint.md +54 -1
- data/doc/plugins/entity.md +1 -0
- data/doc/plugins/form_assign.md +53 -0
- data/doc/plugins/mirroring.md +37 -16
- data/doc/plugins/multi_cache.md +22 -0
- data/doc/plugins/presign_endpoint.md +1 -1
- data/doc/plugins/remote_url.md +19 -4
- data/doc/plugins/validation.md +83 -0
- data/doc/processing.md +149 -133
- data/doc/refile.md +68 -63
- data/doc/release_notes/3.0.0.md +835 -0
- data/doc/securing_uploads.md +56 -36
- data/doc/storage/s3.md +2 -2
- data/doc/testing.md +104 -120
- data/doc/upgrading_to_3.md +538 -0
- data/doc/validation.md +48 -87
- data/lib/shrine.rb +7 -4
- data/lib/shrine/attacher.rb +16 -6
- data/lib/shrine/plugins/activerecord.rb +33 -14
- data/lib/shrine/plugins/atomic_helpers.rb +1 -1
- data/lib/shrine/plugins/backgrounding.rb +23 -89
- data/lib/shrine/plugins/data_uri.rb +13 -2
- data/lib/shrine/plugins/derivation_endpoint.rb +7 -11
- data/lib/shrine/plugins/derivatives.rb +44 -20
- data/lib/shrine/plugins/download_endpoint.rb +26 -0
- data/lib/shrine/plugins/form_assign.rb +6 -3
- data/lib/shrine/plugins/keep_files.rb +2 -2
- data/lib/shrine/plugins/mirroring.rb +62 -22
- data/lib/shrine/plugins/model.rb +2 -2
- data/lib/shrine/plugins/multi_cache.rb +27 -0
- data/lib/shrine/plugins/remote_url.rb +25 -10
- data/lib/shrine/plugins/remove_invalid.rb +1 -1
- data/lib/shrine/plugins/sequel.rb +39 -20
- data/lib/shrine/plugins/validation.rb +3 -0
- data/lib/shrine/storage/s3.rb +16 -1
- data/lib/shrine/uploaded_file.rb +1 -0
- data/lib/shrine/version.rb +1 -1
- data/shrine.gemspec +1 -1
- metadata +12 -7
- data/doc/migrating_storage.md +0 -76
- data/doc/regenerating_versions.md +0 -143
- data/lib/shrine/plugins/attacher_options.rb +0 -55
data/doc/refile.md
CHANGED
@@ -32,14 +32,14 @@ configured differently depending on the types of files you're uploading:
|
|
32
32
|
|
33
33
|
```rb
|
34
34
|
class ImageUploader < Shrine
|
35
|
-
add_metadata :exif do |io
|
35
|
+
add_metadata :exif do |io|
|
36
36
|
MiniMagick::Image.new(io).exif
|
37
37
|
end
|
38
38
|
end
|
39
39
|
```
|
40
40
|
```rb
|
41
41
|
class VideoUploader < Shrine
|
42
|
-
add_metadata :duration do |io
|
42
|
+
add_metadata :duration do |io|
|
43
43
|
FFMPEG::Movie.new(io.path).duration
|
44
44
|
end
|
45
45
|
end
|
@@ -47,43 +47,35 @@ end
|
|
47
47
|
|
48
48
|
### Processing
|
49
49
|
|
50
|
-
|
51
|
-
|
52
|
-
Shrine, on the other hand, generates URLs to specific storages and offers
|
53
|
-
processing on upload (like CarrierWave and Paperclip), but doesn't support
|
54
|
-
on-the-fly processing.
|
55
|
-
|
56
|
-
The reason for this decision is that an image server is a completely separate
|
57
|
-
responsibility, and it's better to use any of the generic services for
|
58
|
-
on-the-fly processing. Shrine already has integrations for many such services:
|
59
|
-
[shrine-cloudinary], [shrine-imgix], and [shrine-uploadcare]. There is even
|
60
|
-
an open-source solution, [Attache], which you can also use with Shrine.
|
61
|
-
|
62
|
-
This is how you would process multiple versions in Shrine:
|
50
|
+
Shrine provides on-the-fly processing via the
|
51
|
+
[`derivation_endpoint`][derivation_endpoint] plugin:
|
63
52
|
|
53
|
+
```rb
|
54
|
+
# config/routes.rb (Rails)
|
55
|
+
Rails.application.routes.draw do
|
56
|
+
# ...
|
57
|
+
mount ImageUploader.derivation_endpoint => "/derivations/image"
|
58
|
+
end
|
59
|
+
```
|
64
60
|
```rb
|
65
61
|
require "image_processing/mini_magick"
|
66
62
|
|
67
63
|
class ImageUploader < Shrine
|
68
|
-
plugin :
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
versions[:large] = pipeline.resize_to_limit!(800, 800)
|
78
|
-
versions[:medium] = pipeline.resize_to_limit!(500, 500)
|
79
|
-
versions[:small] = pipeline.resize_to_limit!(300, 300)
|
80
|
-
end
|
81
|
-
|
82
|
-
versions # return the hash of processed files
|
64
|
+
plugin :derivation_endpoint,
|
65
|
+
secret_key: "<YOUR SECRET KEY>",
|
66
|
+
prefix: "derivations/image" # needs to match the mount point in routes
|
67
|
+
|
68
|
+
derivation :thumbnail do |file, width, height|
|
69
|
+
ImageProcessing::MiniMagick
|
70
|
+
.source(file)
|
71
|
+
.resize_to_limit!(width.to_i, height.to_i)
|
83
72
|
end
|
84
73
|
end
|
85
74
|
```
|
86
75
|
|
76
|
+
Shrine also support processing up front using the [`derivatives`][derivatives]
|
77
|
+
plugin.
|
78
|
+
|
87
79
|
### URL
|
88
80
|
|
89
81
|
While Refile serves all files through the Rack endpoint mounted in your app,
|
@@ -99,7 +91,7 @@ Refile.attachment_url(@photo, :image) #=> "/attachments/cache/50dfl833lfs0gfh.jp
|
|
99
91
|
|
100
92
|
If you're using storage which don't expose files over URL (e.g. a database
|
101
93
|
storage), or you want to secure your downloads, you can also serve files
|
102
|
-
through your app using the download_endpoint plugin.
|
94
|
+
through your app using the [`download_endpoint`][download_endpoint] plugin.
|
103
95
|
|
104
96
|
## Attachments
|
105
97
|
|
@@ -118,11 +110,10 @@ end
|
|
118
110
|
```rb
|
119
111
|
class ImageUploader < Shrine
|
120
112
|
plugin :sequel
|
121
|
-
plugin :keep_files, destroyed: true
|
122
113
|
end
|
123
114
|
|
124
115
|
class Photo < Sequel::Model
|
125
|
-
include ImageUploader::Attachment
|
116
|
+
include ImageUploader::Attachment(:image)
|
126
117
|
end
|
127
118
|
```
|
128
119
|
|
@@ -178,16 +169,16 @@ class ImageUploader < Shrine
|
|
178
169
|
plugin :validation_helpers
|
179
170
|
|
180
171
|
Attacher.validate do
|
181
|
-
|
182
|
-
|
183
|
-
validate_max_size 10*1024*1024
|
172
|
+
validate_extension %w[jpg jpeg png gif]
|
173
|
+
validate_mime_type %w[image/jpeg image/png image/gif]
|
174
|
+
validate_max_size 10*1024*1024
|
184
175
|
end
|
185
176
|
end
|
186
177
|
```
|
187
178
|
|
188
179
|
Refile extracts the MIME type from the file extension, which means it can
|
189
180
|
easily be spoofed (just give a PHP file a `.jpg` extension). Shrine has the
|
190
|
-
determine_mime_type plugin for determining MIME type from file *content*.
|
181
|
+
`determine_mime_type` plugin for determining MIME type from file *content*.
|
191
182
|
|
192
183
|
### Multiple uploads
|
193
184
|
|
@@ -228,25 +219,39 @@ Afterwards we need to make new uploads write to the `image_data` column. This
|
|
228
219
|
can be done by including the below module to all models that have Refile
|
229
220
|
attachments:
|
230
221
|
|
222
|
+
```rb
|
223
|
+
require "shrine"
|
224
|
+
|
225
|
+
Shrine.storages = {
|
226
|
+
cache: ...,
|
227
|
+
store: ...,
|
228
|
+
}
|
229
|
+
|
230
|
+
Shrine.plugin :model
|
231
|
+
```
|
231
232
|
```rb
|
232
233
|
module RefileShrineSynchronization
|
233
234
|
def write_shrine_data(name)
|
234
|
-
|
235
|
-
data = {
|
236
|
-
storage: :store,
|
237
|
-
id: send("#{name}_id"),
|
238
|
-
metadata: {
|
239
|
-
size: (send("#{name}_size") if respond_to?("#{name}_size")),
|
240
|
-
filename: (send("#{name}_filename") if respond_to?("#{name}_filename")),
|
241
|
-
mime_type: (send("#{name}_content_type") if respond_to?("#{name}_content_type")),
|
242
|
-
}
|
243
|
-
}
|
235
|
+
attacher = Shrine::Attacher.from_model(self, name)
|
244
236
|
|
245
|
-
|
237
|
+
if read_attribute("#{name}_id").present?
|
238
|
+
attacher.set shrine_file(name)
|
246
239
|
else
|
247
|
-
|
240
|
+
attacher.set nil
|
248
241
|
end
|
249
242
|
end
|
243
|
+
|
244
|
+
def shrine_file(name)
|
245
|
+
Shrine.uploaded_file(
|
246
|
+
storage: :store,
|
247
|
+
id: send("#{name}_id"),
|
248
|
+
metadata: {
|
249
|
+
"size" => (send("#{name}_size") if respond_to?("#{name}_size")),
|
250
|
+
"filename" => (send("#{name}_filename") if respond_to?("#{name}_filename")),
|
251
|
+
"mime_type" => (send("#{name}_content_type") if respond_to?("#{name}_content_type")),
|
252
|
+
}
|
253
|
+
)
|
254
|
+
end
|
250
255
|
end
|
251
256
|
```
|
252
257
|
```rb
|
@@ -293,8 +298,9 @@ Shrine.storages = {
|
|
293
298
|
|
294
299
|
#### `.app`, `.mount_point`, `.automount`
|
295
300
|
|
296
|
-
The `upload_endpoint` and `
|
297
|
-
generating Rack apps, but you need to mount them
|
301
|
+
The `upload_endpoint`, `presign_endpoint`, and `derivation_endpoint` plugins
|
302
|
+
provide methods for generating Rack apps, but you need to mount them
|
303
|
+
explicitly:
|
298
304
|
|
299
305
|
```rb
|
300
306
|
# config/routes.rb
|
@@ -318,10 +324,10 @@ Shrine.logger
|
|
318
324
|
#### `.processors`, `.processor`
|
319
325
|
|
320
326
|
```rb
|
321
|
-
class
|
322
|
-
plugin :
|
327
|
+
class ImageUploader < Shrine
|
328
|
+
plugin :derivatives
|
323
329
|
|
324
|
-
|
330
|
+
derivation :thumbnail do |file, width, height|
|
325
331
|
# ...
|
326
332
|
end
|
327
333
|
end
|
@@ -329,7 +335,7 @@ end
|
|
329
335
|
|
330
336
|
#### `.types`
|
331
337
|
|
332
|
-
In Shrine validations are done by calling `.validate` on the attacher class:
|
338
|
+
In Shrine, validations are done by calling `.validate` on the attacher class:
|
333
339
|
|
334
340
|
```rb
|
335
341
|
class MyUploader < Shrine
|
@@ -375,8 +381,8 @@ Shrine's equivalent to calling the attachment is including an attachment module
|
|
375
381
|
of an uploader:
|
376
382
|
|
377
383
|
```rb
|
378
|
-
class
|
379
|
-
include ImageUploader::Attachment
|
384
|
+
class Photo
|
385
|
+
include ImageUploader::Attachment(:image)
|
380
386
|
end
|
381
387
|
```
|
382
388
|
|
@@ -390,8 +396,8 @@ class ImageUploader < Shrine
|
|
390
396
|
plugin :validation_helpers
|
391
397
|
|
392
398
|
Attacher.validate do
|
393
|
-
|
394
|
-
|
399
|
+
validate_extension %w[jpg jpeg png]
|
400
|
+
validate_mime_type %w[image/jpeg image/png]
|
395
401
|
end
|
396
402
|
end
|
397
403
|
```
|
@@ -477,12 +483,11 @@ form_for @user do |form|
|
|
477
483
|
end
|
478
484
|
```
|
479
485
|
|
480
|
-
[shrine-cloudinary]: https://github.com/shrinerb/shrine-cloudinary
|
481
|
-
[shrine-imgix]: https://github.com/shrinerb/shrine-imgix
|
482
|
-
[shrine-uploadcare]: https://github.com/shrinerb/shrine-uploadcare
|
483
|
-
[Attache]: https://github.com/choonkeat/attache
|
484
486
|
[image_processing]: https://github.com/janko/image_processing
|
485
487
|
[Uppy]: https://uppy.io
|
486
488
|
[Direct Uploads to S3]: /doc/direct_s3.md#readme
|
487
489
|
[demo app]: https://github.com/shrinerb/shrine/tree/master/demo
|
488
490
|
[Multiple Files]: /doc/multiple_files.md#readme
|
491
|
+
[derivation_endpoint]: /doc/plugins/derivation_endpoint.md#readme
|
492
|
+
[download_endpoint]: /doc/plugins/download_endpoint.md#readme
|
493
|
+
[derivatives]: /doc/plugins/derivatives.md#readme
|
@@ -0,0 +1,835 @@
|
|
1
|
+
# Shrine 3.0.0
|
2
|
+
|
3
|
+
This guide covers all the changes in the 3.0.0 version of Shrine. If you're
|
4
|
+
currently using Shrine 2.x, see [Upgrading to Shrine 3.x] for instructions on
|
5
|
+
how to upgrade.
|
6
|
+
|
7
|
+
## Major features
|
8
|
+
|
9
|
+
* The new **[`derivatives`][derivatives]** plugin has been added for storing
|
10
|
+
additional processed files alongside the main file.
|
11
|
+
|
12
|
+
```rb
|
13
|
+
Shrine.plugin :derivatives
|
14
|
+
```
|
15
|
+
```rb
|
16
|
+
class ImageUploader < Shrine
|
17
|
+
Attacher.derivatives_processor do |original|
|
18
|
+
magick = ImageProcessing::MiniMagick.source(original)
|
19
|
+
|
20
|
+
{
|
21
|
+
large: magick.resize_to_limit!(800, 800),
|
22
|
+
medium: magick.resize_to_limit!(500, 500),
|
23
|
+
small: magick.resize_to_limit!(300, 300),
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
```
|
28
|
+
```rb
|
29
|
+
photo = Photo.new(photo_params)
|
30
|
+
photo.image_derivatives! # creates derivatives
|
31
|
+
photo.save
|
32
|
+
```
|
33
|
+
|
34
|
+
This is a rewrite of the [`versions`][versions] plugin, bringing numerous
|
35
|
+
improvements:
|
36
|
+
|
37
|
+
- processed files are separated from the main file
|
38
|
+
- processing is decoupled from promotion
|
39
|
+
- ability to add or remove processed files at any point
|
40
|
+
- possibility of storing processed files on a separate storage
|
41
|
+
|
42
|
+
* The [`Shrine::Attacher`][attacher] class has been rewritten and can now be
|
43
|
+
used without models:
|
44
|
+
|
45
|
+
```rb
|
46
|
+
attacher = Shrine::Attacher.new
|
47
|
+
attacher.attach(file)
|
48
|
+
attacher.file #=> #<Shrine::UploadedFile>
|
49
|
+
```
|
50
|
+
|
51
|
+
The `Attacher#data`, `Attacher#load_data`, and `Attacher.from_data` methods
|
52
|
+
have been added for dumping and loading the attached file:
|
53
|
+
|
54
|
+
```rb
|
55
|
+
# dump attached file into a serializable Hash
|
56
|
+
data = attacher.data #=> { "id" => "abc123.jpg", "storage" => "store", "metadata" => { ... } }
|
57
|
+
```
|
58
|
+
```rb
|
59
|
+
# initialize attacher from attached file data...
|
60
|
+
attacher = Shrine::Attacher.from_data(data)
|
61
|
+
attacher.file #=> #<Shrine::UploadedFile @id="abc123.jpg" @storage_key=:store @metadata={...}>
|
62
|
+
|
63
|
+
# ...or load attached file into an existing attacher
|
64
|
+
attacher = Shrine::Attacher.new
|
65
|
+
attacher.load_data(data)
|
66
|
+
attacher.file #=> #<Shrine::UploadedFile>
|
67
|
+
```
|
68
|
+
|
69
|
+
Several more methods have been added:
|
70
|
+
|
71
|
+
- `Attacher#attach` – attaches the file directly to permanent storage
|
72
|
+
- `Attacher#attach_cached` – extracted from `Attacher#assign`
|
73
|
+
- `Attacher#upload` – calls `Shrine#upload`, passing `:record` and `:name` context
|
74
|
+
- `Attacher#file` – alias for `Attacher#get`
|
75
|
+
- `Attacher#cache_key` – returns temporary storage key (`:cache` by default)
|
76
|
+
- `Attacher#store_key` – returns permanent storage key (`:store` by default)
|
77
|
+
|
78
|
+
* The new [`column`][column] plugin adds the ability to serialize attached file
|
79
|
+
data, in format suitable for writing into a database column.
|
80
|
+
|
81
|
+
```rb
|
82
|
+
Shrine.plugin :column
|
83
|
+
```
|
84
|
+
```rb
|
85
|
+
# dump attached file data into a JSON string
|
86
|
+
data = attacher.column_data #=> '{"id":"abc123.jpg","storage":"store","metadata":{...}}'
|
87
|
+
```
|
88
|
+
```rb
|
89
|
+
# initialize attacher from attached file data...
|
90
|
+
attacher = Shrine::Attacher.from_column(data)
|
91
|
+
attacher.file #=> #<Shrine::UploadedFile @id="abc123.jpg" @storage_key=:store @metadata={...}>
|
92
|
+
|
93
|
+
# ...or load attached file into an existing attacher
|
94
|
+
attacher = Shrine::Attacher.new
|
95
|
+
attacher.load_column(data)
|
96
|
+
attacher.file #=> #<Shrine::UploadedFile>
|
97
|
+
```
|
98
|
+
|
99
|
+
* The new [`entity`][entity] plugin adds support for immutable structs, which
|
100
|
+
are commonly used with ROM, Hanami and dry-rb.
|
101
|
+
|
102
|
+
```rb
|
103
|
+
Shrine.plugin :entity
|
104
|
+
```
|
105
|
+
```rb
|
106
|
+
class Photo < Hanami::Entity
|
107
|
+
include Shrine::Attachment(:image)
|
108
|
+
end
|
109
|
+
```
|
110
|
+
```rb
|
111
|
+
photo = Photo.new(image_data: '{"id":"abc123.jpg","storage":"store","metadata":{...}}')
|
112
|
+
photo.image #=> #<Shrine::UploadedFile @id="abc123.jpg" @storage_key=:store ...>
|
113
|
+
```
|
114
|
+
|
115
|
+
* The new [`model`][model] plugin adds support for mutable structs, which is
|
116
|
+
used for `activerecord` and `sequel` plugins.
|
117
|
+
|
118
|
+
```rb
|
119
|
+
Shrine.plugin :model
|
120
|
+
```
|
121
|
+
```rb
|
122
|
+
class Photo < Struct.new(:image_data)
|
123
|
+
include Shrine::Attachment(:image)
|
124
|
+
end
|
125
|
+
```
|
126
|
+
```rb
|
127
|
+
photo = Photo.new
|
128
|
+
photo.image = file
|
129
|
+
photo.image #=> #<Shrine::UploadedFile @id="abc123.jpg" @storage_key=:cache ...>
|
130
|
+
photo.image_data #=> #=> '{"id":"abc123.jpg", "storage":"cache", "metadata":{...}}'
|
131
|
+
```
|
132
|
+
|
133
|
+
* The [`backgrounding`][backgrounding] plugin has been rewritten for more
|
134
|
+
flexibility and simplicity. The new usage is much more explicit:
|
135
|
+
|
136
|
+
```rb
|
137
|
+
Shrine.plugin :backgrounding
|
138
|
+
Shrine::Attacher.promote_block { PromoteJob.promote_later(self.class, record, name, file_data) }
|
139
|
+
Shrine::Attacher.destroy_block { DestroyJob.promote_later(self.class, data) }
|
140
|
+
```
|
141
|
+
```rb
|
142
|
+
class PromoteJob < ActiveJob::Base
|
143
|
+
def perform(attacher_class, record, name, file_data)
|
144
|
+
attacher = attacher_class.retrieve(model: record, name: name, file: file_data)
|
145
|
+
attacher.atomic_promote # promote if attachment hasn't changed
|
146
|
+
rescue Shrine::AttachmentChanged, ActiveRecord::RecordNotFound
|
147
|
+
# attachment has changed or record has been deleted, nothing to do
|
148
|
+
end
|
149
|
+
end
|
150
|
+
```
|
151
|
+
```rb
|
152
|
+
class DestroyJob < ActiveJob::Base
|
153
|
+
def perform(attacher_class, data)
|
154
|
+
attacher = attacher_class.from_data(data)
|
155
|
+
attacher.destroy
|
156
|
+
end
|
157
|
+
end
|
158
|
+
```
|
159
|
+
|
160
|
+
There are several main differences compared to the old implementation:
|
161
|
+
|
162
|
+
- we are in charge of passing the record to the background job
|
163
|
+
- we can access the attacher before promotion
|
164
|
+
- we can react to errors that caused promotion to abort
|
165
|
+
|
166
|
+
We can now also register backgrounding hooks on an attacher instance, allowing
|
167
|
+
us to pass additional parameters to the background job:
|
168
|
+
|
169
|
+
```rb
|
170
|
+
photo = Photo.new(photo_params)
|
171
|
+
|
172
|
+
photo.image_attacher.promote_block do |attacher|
|
173
|
+
PromoteJob.perform_later(
|
174
|
+
attacher.class,
|
175
|
+
attacher.record,
|
176
|
+
attacher.name,
|
177
|
+
attacher.file_data,
|
178
|
+
current_user.id, # <== parameters from the controller
|
179
|
+
)
|
180
|
+
end
|
181
|
+
|
182
|
+
photo.save # will call our instance-level backgrounding hook
|
183
|
+
```
|
184
|
+
|
185
|
+
* The persistence plugins (`activerecord`, `sequel`) now implement a unified
|
186
|
+
[persistence] interface:
|
187
|
+
|
188
|
+
| Method | Description |
|
189
|
+
| :----------------- | :---------- |
|
190
|
+
| `Attacher#persist` | persists attachment data |
|
191
|
+
| `Attacher#atomic_persist` | persists attachment data if attachment hasn’t changed |
|
192
|
+
| `Attacher#atomic_promote` | promotes cached file and atomically persists changes |
|
193
|
+
|
194
|
+
The "atomic" methods use the new [`atomic_helpers`][atomic_helpers] plugin,
|
195
|
+
and are useful for background jobs. For example, this is how we'd use them to
|
196
|
+
implement metadata extraction in the background in a concurrency-safe way:
|
197
|
+
|
198
|
+
```rb
|
199
|
+
MetadataJob.perform_later(
|
200
|
+
attacher.class,
|
201
|
+
attacher.record,
|
202
|
+
attacher.name,
|
203
|
+
attacher.file_data,
|
204
|
+
)
|
205
|
+
```
|
206
|
+
```rb
|
207
|
+
class MetadataJob < ActiveJob::Base
|
208
|
+
def perform(attacher_class, record, name, file_data)
|
209
|
+
attacher = attacher_class.retrieve(model: record, name: name, file: file_data)
|
210
|
+
attacher.refresh_metadata! # extract metadata
|
211
|
+
attacher.atomic_persist # persist if attachment hasn't changed
|
212
|
+
rescue Shrine::AttachmentChanged, ActiveRecord::RecordNotFound
|
213
|
+
# attachment has changed or record has been deleted, nothing to do
|
214
|
+
end
|
215
|
+
end
|
216
|
+
```
|
217
|
+
|
218
|
+
## Other features
|
219
|
+
|
220
|
+
* The new [`mirroring`][mirroring] plugin has been added for replicating
|
221
|
+
uploads and deletes to other storages.
|
222
|
+
|
223
|
+
```rb
|
224
|
+
Shrine.storages = { cache: ..., store: ..., backup: ... }
|
225
|
+
|
226
|
+
Shrine.plugin :mirroring, mirror: { store: :backup }
|
227
|
+
```
|
228
|
+
```rb
|
229
|
+
file = Shrine.upload(io, :store) # uploads to :store and :backup
|
230
|
+
file.delete # deletes from :store and :backup
|
231
|
+
```
|
232
|
+
|
233
|
+
* The new [`multi_cache`][multi_cache] plugin has been added for allowing an
|
234
|
+
attacher to accept files from additional temporary storages.
|
235
|
+
|
236
|
+
```rb
|
237
|
+
Shrine.storages = { cache: ..., cache_one: ..., cache_two: ..., store: ... }
|
238
|
+
|
239
|
+
Shrine.plugin :multi_cache, additional_cache: [:cache_one, :cache_two]
|
240
|
+
```
|
241
|
+
```rb
|
242
|
+
photo.image = { "id" => "...", "storage" => "cache", "metadata" => { ... } }
|
243
|
+
photo.image.storage_key #=> :cache
|
244
|
+
# or
|
245
|
+
photo.image = { "id" => "...", "storage" => "cache_one", "metadata" => { ... } }
|
246
|
+
photo.image.storage_key #=> :cache_one
|
247
|
+
# or
|
248
|
+
photo.image = { "id" => "...", "storage" => "cache_two", "metadata" => { ... } }
|
249
|
+
photo.image.storage_key #=> :cache_two
|
250
|
+
```
|
251
|
+
|
252
|
+
* The new [`form_assign`][form_assign] plugin has been added for assigning
|
253
|
+
files directly from form params.
|
254
|
+
|
255
|
+
```rb
|
256
|
+
Shrine.plugin :form_assign
|
257
|
+
```
|
258
|
+
```rb
|
259
|
+
attacher = photo.image_attacher
|
260
|
+
attacher.form_assign("image" => file, "title" => "...", "description" => "...")
|
261
|
+
attacher.file #=> #<Shrine::UploadedFile @id="..." @storage_key=:cache ...>
|
262
|
+
```
|
263
|
+
|
264
|
+
* Model file assignment can now be configured to upload directly to permanent
|
265
|
+
storage.
|
266
|
+
|
267
|
+
```rb
|
268
|
+
Shrine.plugin :model, cache: false
|
269
|
+
```
|
270
|
+
```rb
|
271
|
+
photo.image = file
|
272
|
+
photo.image.storage_key #=> :store (permanent storage)
|
273
|
+
```
|
274
|
+
|
275
|
+
* New `Shrine.download_response` method has been added to the
|
276
|
+
`download_endpoint` plugin for generating file response from the controller.
|
277
|
+
|
278
|
+
```rb
|
279
|
+
Rails.application.routes.draw do
|
280
|
+
get "/attachments" => "files#download"
|
281
|
+
end
|
282
|
+
```
|
283
|
+
```rb
|
284
|
+
class FilesController < ApplicationController
|
285
|
+
def download
|
286
|
+
# ... we can now perform things like authentication here ...
|
287
|
+
set_rack_response Shrine.download_response(env)
|
288
|
+
end
|
289
|
+
|
290
|
+
private
|
291
|
+
|
292
|
+
def set_rack_response((status, headers, body))
|
293
|
+
self.status = status
|
294
|
+
self.headers.merge!(headers)
|
295
|
+
self.response_body = body
|
296
|
+
end
|
297
|
+
end
|
298
|
+
```
|
299
|
+
|
300
|
+
* The `Attacher#refresh_metadata!` method has been added to `refresh_metadata`
|
301
|
+
plugin. It refreshes metadata and writes new attached file data back into the
|
302
|
+
data attribute.
|
303
|
+
|
304
|
+
```rb
|
305
|
+
attacher.file.refresh_metadata!
|
306
|
+
attacher.write
|
307
|
+
# can now be shortened to
|
308
|
+
attacher.refresh_metadata!
|
309
|
+
```
|
310
|
+
|
311
|
+
* Including a `Shrine::Attachment` module now defines a `.<name>_attacher`
|
312
|
+
class method on the target class.
|
313
|
+
|
314
|
+
```rb
|
315
|
+
class Photo
|
316
|
+
include ImageUploader::Attachment(:image)
|
317
|
+
|
318
|
+
image_attacher #=> #<ImageUploader::Attacher ...>
|
319
|
+
end
|
320
|
+
```
|
321
|
+
|
322
|
+
* The attachment data serializer is now configurable (by default `JSON`
|
323
|
+
standard library is used):
|
324
|
+
|
325
|
+
```rb
|
326
|
+
require "oj" # https://github.com/ohler55/oj
|
327
|
+
|
328
|
+
Shrine.plugin :column, serializer: Oj
|
329
|
+
```
|
330
|
+
|
331
|
+
* It's now possible to pass options to the validate block via the `:validate`
|
332
|
+
option:
|
333
|
+
|
334
|
+
```rb
|
335
|
+
attacher.assign(file, validate: { foo: "bar" })
|
336
|
+
```
|
337
|
+
```rb
|
338
|
+
class MyUploader < Shrine
|
339
|
+
Attacher.validate do |**options|
|
340
|
+
options #=> { foo: "bar" }
|
341
|
+
end
|
342
|
+
end
|
343
|
+
```
|
344
|
+
|
345
|
+
* Validation can now be skipped on assignment by passing `validate: false`.
|
346
|
+
|
347
|
+
```rb
|
348
|
+
attacher.attach(file, validate: false) # skip validation
|
349
|
+
```
|
350
|
+
|
351
|
+
* Closing the uploaded file can now be prevented by passing `close: false` to
|
352
|
+
`Shrine#upload`.
|
353
|
+
|
354
|
+
* Uploaded file can now be automatically deleted by passing `delete: true` to
|
355
|
+
`Shrine#upload`.
|
356
|
+
|
357
|
+
* New `Attacher#file!` method has been added for retrieving the attached file
|
358
|
+
and raising and exception if it doesn't exist.
|
359
|
+
|
360
|
+
* New `Derivation#opened` method has been added for retrieving an opened
|
361
|
+
derivative in `derivation_endpoint` plugin.
|
362
|
+
|
363
|
+
## Performance improvements
|
364
|
+
|
365
|
+
* The attached file is now parsed and loaded from record column only once,
|
366
|
+
which can greatly improve performance if the same attached file is being
|
367
|
+
accessed multiple times.
|
368
|
+
|
369
|
+
```rb
|
370
|
+
photo = Photo.find(photo_id)
|
371
|
+
photo.image # parses and loads attached file
|
372
|
+
photo.image # returns memoized attached file
|
373
|
+
```
|
374
|
+
|
375
|
+
* The `S3#open` method doesn't perform a `#head_obect` request anymore.
|
376
|
+
|
377
|
+
* The `derivation_endpoint` plugin doesn't perform a `Storage#exists?` call
|
378
|
+
anymore when `:upload` is enabled.
|
379
|
+
|
380
|
+
* The `download_endpoint` plugin doesn't perform a `Storage#exists?` call
|
381
|
+
anymore.
|
382
|
+
|
383
|
+
## Other Improvements
|
384
|
+
|
385
|
+
* The `Attacher#assign` method now accepts cached file data as a Hash.
|
386
|
+
|
387
|
+
```rb
|
388
|
+
photo.image = { "id" => "...", "storage" => "cache", "metadata" => { ... } }
|
389
|
+
````
|
390
|
+
|
391
|
+
* An `UploadedFile` object can now be initialized with symbol keys.
|
392
|
+
|
393
|
+
```rb
|
394
|
+
Shrine.uploaded_file(id: "...", storage: :store, metadata: { ... })
|
395
|
+
```
|
396
|
+
|
397
|
+
* The temporary storage doesn't need to be defined anymore if it's not used.
|
398
|
+
|
399
|
+
* The memory storage from the [shrine-memory] gem has been merged into core.
|
400
|
+
|
401
|
+
```rb
|
402
|
+
# Gemfile
|
403
|
+
gem "shrine-memory" # this can be removed
|
404
|
+
```
|
405
|
+
|
406
|
+
* When copying the S3 object to another location, any specified upload options
|
407
|
+
will now be applied.
|
408
|
+
|
409
|
+
* The `url_options` plugin now allows you to override URL options by deleting
|
410
|
+
them.
|
411
|
+
|
412
|
+
```rb
|
413
|
+
uploaded_file.url(response_content_disposition: "attachment")
|
414
|
+
```
|
415
|
+
```rb
|
416
|
+
plugin :url_options, store: -> (io, options) {
|
417
|
+
disposition = options.delete(:response_content_disposition, "inline")
|
418
|
+
|
419
|
+
{
|
420
|
+
response_content_disposition: ContentDisposition.format(
|
421
|
+
disposition: disposition,
|
422
|
+
filename: io.original_filename,
|
423
|
+
)
|
424
|
+
}
|
425
|
+
}
|
426
|
+
```
|
427
|
+
|
428
|
+
* The `:upload_options` hash passed to the uploader is now merged with any
|
429
|
+
options defined with the `upload_options` plugin.
|
430
|
+
|
431
|
+
* The `default_storage` now evaluates the storage block in context of the
|
432
|
+
`Attacher` instance.
|
433
|
+
|
434
|
+
* New `Attacher.default_cache` and `Attacher.default_store` methods have been
|
435
|
+
added to the `default_storage` plugin for declaratively setting default
|
436
|
+
storage.
|
437
|
+
|
438
|
+
```rb
|
439
|
+
Attacher.default_cache { ... }
|
440
|
+
Attacher.default_store { ... }
|
441
|
+
```
|
442
|
+
|
443
|
+
* The `derivation_endpoint` plugin now handles string derivation names.
|
444
|
+
|
445
|
+
* The `Derivation#upload` method from `derivation_endpoint` plugin now accepts
|
446
|
+
additional uploader options
|
447
|
+
|
448
|
+
* The `Derivation#upload` method from `derivation_endpoint` plugin now accepts
|
449
|
+
any IO-like object.
|
450
|
+
|
451
|
+
* The `instrumentation` plugin now instruments `UploadedFile#open` calls as a
|
452
|
+
new `open.shrine` event. `UploadedFile#download` is still instrumented as
|
453
|
+
`download.shrine`.
|
454
|
+
|
455
|
+
* The `upload.shrine` event now has `:metadata` on the top level in
|
456
|
+
`instrumentation` plugin.
|
457
|
+
|
458
|
+
* The width & height validators in `store_dimensions` plugin don't require
|
459
|
+
`UploadedFile#width` and `UploadedFile#height` methods to be defined anymore,
|
460
|
+
only that the corresponding metadata exists.
|
461
|
+
|
462
|
+
* Any options passed to `Attacher#attach_cached` are now forwarded to metadata
|
463
|
+
extraction when `restore_cached_data` plugin is loaded.
|
464
|
+
|
465
|
+
* Deprecation of passing unknown options to `FileSystem#open` has been
|
466
|
+
reverted. This allows users to continue using `FileSystem` storage in tests
|
467
|
+
as a mock storage.
|
468
|
+
|
469
|
+
* The `activerecord` plugin now works with Active Record 3.
|
470
|
+
|
471
|
+
* Shrine now works again with MRI 2.3.
|
472
|
+
|
473
|
+
* The `infer_extension` plugin now works correctly with `pretty_location`
|
474
|
+
plugin when `pretty_location` was loaded after `infer_extension`.
|
475
|
+
|
476
|
+
* The `derivation_endpoint` plugin doesn't re-open `File` objects returned in
|
477
|
+
derivation block anymore.
|
478
|
+
|
479
|
+
* Any changes to `Shrine.storages` will now be applied to existing `Shrine` and
|
480
|
+
`Attacher` instances.
|
481
|
+
|
482
|
+
* Callback code from `activerecord` and `sequel` plugin has been moved into
|
483
|
+
attacher methods, allowing the user to override them.
|
484
|
+
|
485
|
+
* The `Shrine.opts` hash is now deep-copied on subclassing. This allows plugins
|
486
|
+
to freely mutate hashes and arrays in `Shrine.opts`, knowing they won't be
|
487
|
+
shared across subclasses.
|
488
|
+
|
489
|
+
## Backwards compatibility
|
490
|
+
|
491
|
+
### Plugin deprecation and removal
|
492
|
+
|
493
|
+
* The `backgrounding` plugin has been rewritten and has a new API. While the
|
494
|
+
new API works in a similar way, no backwards compatibility has been kept with
|
495
|
+
the previous API.
|
496
|
+
|
497
|
+
* The `versions`, `processing`, `recache`, and `delete_raw` plugins have been
|
498
|
+
deprecated in favor of the new `derivatives` plugin.
|
499
|
+
|
500
|
+
* The `module_include` plugin has been deprecated over overriding core classes
|
501
|
+
directly.
|
502
|
+
|
503
|
+
* The `hooks`, `parallelize`, `parsed_json`, and `delete_promoted` plugins have
|
504
|
+
been removed.
|
505
|
+
|
506
|
+
* The deprecated `copy`, `backup`, `multi_delete`, `moving`, `logging`,
|
507
|
+
`direct_upload` `background_helpers`, and `migration_helpers` plugins have
|
508
|
+
been removed.
|
509
|
+
|
510
|
+
* The `default_url_options` plugin has been renamed to `url_options`.
|
511
|
+
|
512
|
+
### Attacher API
|
513
|
+
|
514
|
+
* The `Attacher.new` method now only accepts a hash of options.
|
515
|
+
|
516
|
+
```rb
|
517
|
+
# this doesn't work anymore
|
518
|
+
Shrine::Attacher.new(photo, :image) # ~> ArgumentError: invalid number of arguments
|
519
|
+
|
520
|
+
# this should be used instead
|
521
|
+
Shrine::Attacher.from_model(photo, :image)
|
522
|
+
```
|
523
|
+
|
524
|
+
* The attacher won't detect direct data attribute changes anymore. If you're
|
525
|
+
updating the data attribute and are expecting to see the change applied to
|
526
|
+
the attacher, you'll need to call `Attacher#reload`.
|
527
|
+
|
528
|
+
```rb
|
529
|
+
attacher = photo.image_attacher
|
530
|
+
photo.image_data = '...'
|
531
|
+
attacher.reload
|
532
|
+
```
|
533
|
+
|
534
|
+
* The `Attacher#promote` method now only saves the promoted file in memory,
|
535
|
+
it doesn't persist the changes.
|
536
|
+
|
537
|
+
* The `Attacher#_set` and `Attacher#set` methods have been renamed to
|
538
|
+
`Attacher#set` and `Attacher#changed`.
|
539
|
+
|
540
|
+
* The `Attacher#cache!`, `Attacher#store!`, and `Attacher#delete!` methods have
|
541
|
+
been removed.
|
542
|
+
|
543
|
+
* The `Attacher#_promote` and `Attacher#_delete` methods have been removed.
|
544
|
+
|
545
|
+
* The `Attacher#swap`, `Attacher#update`, `Attacher#read`, `Attacher#write`,
|
546
|
+
`Attacher#convert_to_data`, `Attacher#convert_before_write`, and
|
547
|
+
`Attache#convert_after_read` methods have been removed.
|
548
|
+
|
549
|
+
* The `Attacher.validate`, `Attacher#validate` and `Attacher#errors` methods
|
550
|
+
have been extracted into the new `validation` plugin.
|
551
|
+
|
552
|
+
* The `Attacher#data_attribute` method has been renamed to `Attacher#attribute`.
|
553
|
+
|
554
|
+
* The `Attacher#replace` method has been renamed to
|
555
|
+
`Attacher#destroy_previous`.
|
556
|
+
|
557
|
+
* The `Attacher#attached?` method now returns whether a file is attached,
|
558
|
+
regardless of whether it was changed or not.
|
559
|
+
|
560
|
+
### Attachment API
|
561
|
+
|
562
|
+
* The `Shrine::Attachment` module doesn't define any instance methods by itself
|
563
|
+
anymore. This has been moved into `entity` and `model` plugins.
|
564
|
+
|
565
|
+
### Uploader API
|
566
|
+
|
567
|
+
* The `:phase` option has been removed.
|
568
|
+
|
569
|
+
* The `Shrine#process` and `Shrine#processed` methods have been removed.
|
570
|
+
|
571
|
+
* The `Shrine#store`, `Shrine#_store`, `Shrine#put`, and `Shrine#copy` methods
|
572
|
+
have been removed.
|
573
|
+
|
574
|
+
* The `Shrine#delete`, `Shrine#_delete`, and `Shrine#remove` methods have been
|
575
|
+
removed.
|
576
|
+
|
577
|
+
* The `Shrine#uploaded?` method has been removed.
|
578
|
+
|
579
|
+
* The `Shrine.uploaded_file` method doesn't yield files anymore by default.
|
580
|
+
|
581
|
+
* The options for `Shrine#upload` and `Shrine#extract_metadata` are now
|
582
|
+
required to have symbol keys.
|
583
|
+
|
584
|
+
* The `Shrine.uploaded_file` method now raises `ArgumentError` on invalid
|
585
|
+
arguments.
|
586
|
+
|
587
|
+
* The `Shrine#upload` method doesn't rescue exceptions that happen in
|
588
|
+
`IO#close` anymore.
|
589
|
+
|
590
|
+
* The deprecated `Shrine::IO_METHODS` constant has been removed.
|
591
|
+
|
592
|
+
### Uploaded File API
|
593
|
+
|
594
|
+
* The `UploadedFile` method now extracts data from the given hash on
|
595
|
+
initialization, it doesn't store the whole hash anymore. This means the
|
596
|
+
following potential code won't work anymore:
|
597
|
+
|
598
|
+
```rb
|
599
|
+
uploaded_file.id #=> "foo"
|
600
|
+
uploaded_file.data["id"] = "bar"
|
601
|
+
uploaded_file.id #=> "foo"
|
602
|
+
```
|
603
|
+
|
604
|
+
* The `UploadedFile#storage_key` method now returns a Symbol instead of a
|
605
|
+
String.
|
606
|
+
|
607
|
+
```rb
|
608
|
+
# previous behaviour
|
609
|
+
uploaded_file.storage_key #=> "store"
|
610
|
+
|
611
|
+
# new behaviour
|
612
|
+
uploaded_file.storage_key #=> :store
|
613
|
+
```
|
614
|
+
|
615
|
+
* The `UploadedFile#==` method now requires both uploaded file objects to be
|
616
|
+
of the same class.
|
617
|
+
|
618
|
+
### Storage API
|
619
|
+
|
620
|
+
* The `Storage#open` method is now required to accept additional options.
|
621
|
+
|
622
|
+
```rb
|
623
|
+
# this won't work anymore
|
624
|
+
def open(id)
|
625
|
+
# ...
|
626
|
+
end
|
627
|
+
|
628
|
+
# this is now required
|
629
|
+
def open(id, **options)
|
630
|
+
# ...
|
631
|
+
end
|
632
|
+
```
|
633
|
+
|
634
|
+
* The `Storage#open` method is now required to raise `Shrine::FileNotFound`
|
635
|
+
exception when the file is missing.
|
636
|
+
|
637
|
+
### S3 API
|
638
|
+
|
639
|
+
* The support for `aws-sdk` 2.x and `aws-sdk-s3` lower than 1.14 has been
|
640
|
+
removed.
|
641
|
+
|
642
|
+
* `S3#open` now raises `Shrine::FileNotFound` exception when S3 object doesn't
|
643
|
+
exist on the bucket.
|
644
|
+
|
645
|
+
* The `S3#upload` method will now override any S3 object data when copying
|
646
|
+
from another S3 object. If you were relying on S3 object data being inherited
|
647
|
+
on copy, you will need to update your code.
|
648
|
+
|
649
|
+
* The `:host` option in `S3#initialize` has been removed.
|
650
|
+
|
651
|
+
* The `:download` option in `S3#url` has been removed.
|
652
|
+
|
653
|
+
* Specifying `:multipart_threshold` as an integer is not supported anymore.
|
654
|
+
|
655
|
+
* Non URI-escaped `:content_disposition` and `:response_content_disposition`
|
656
|
+
values are not supported anymore.
|
657
|
+
|
658
|
+
* The `S3#presign` method now returns a hash instead of an object for default
|
659
|
+
POST method.
|
660
|
+
|
661
|
+
* The deprecated `S3#stream`, `S3#download`, and `S3#s3` methods have been
|
662
|
+
removed.
|
663
|
+
|
664
|
+
* The `S3#open` method doesn't include an `:object` in `Down::ChunkedIO#data`
|
665
|
+
anymore.
|
666
|
+
|
667
|
+
### FileSystem API
|
668
|
+
|
669
|
+
* `FileSystem#open` now raises `Shrine::FileNotFound` exception when file does
|
670
|
+
not exist on the filesystem.
|
671
|
+
|
672
|
+
* The deprecated `:host` option in `FileSystem#initialize` has been removed.
|
673
|
+
|
674
|
+
* The deprecated `:older_than` option in `FileSystem#clear!` has been removed.
|
675
|
+
|
676
|
+
* The deprecated `FileSystem#download` method has been removed.
|
677
|
+
|
678
|
+
* The `FileSystem#movable?` and `FileSystem#move` methods have been made
|
679
|
+
private.
|
680
|
+
|
681
|
+
* The `FileSystem#open` method doesn't accept a block anymore.
|
682
|
+
|
683
|
+
### Plugins API
|
684
|
+
|
685
|
+
* `remote_url`
|
686
|
+
|
687
|
+
- A custom downloader is now required to raise
|
688
|
+
`Shrine::Plugins::RemoteUrl::DownloadError` in order for the exception to
|
689
|
+
be converted into a validation error. `Down::NotFound` and `Down::TooLarge`
|
690
|
+
exceptions are converted by default. All other exceptions are propagated.
|
691
|
+
|
692
|
+
* `upload_endpoint`
|
693
|
+
|
694
|
+
- The deprecated `Shrine::Plugins::UploadEndpoint::App` constant has been
|
695
|
+
removed.
|
696
|
+
|
697
|
+
- The `:request` option holding the `Rack::Request` object isn't passed to
|
698
|
+
the uploader anymore.
|
699
|
+
|
700
|
+
* `presign_endpoint`
|
701
|
+
|
702
|
+
- `Storage#presign` results that cannot coerce themselves into a Hash are not
|
703
|
+
supported anymore.
|
704
|
+
|
705
|
+
- The deprecated `Shrine::Plugins::PresignEndpoint::App` constant has been
|
706
|
+
removed.
|
707
|
+
|
708
|
+
* `derivation_endpoint`
|
709
|
+
|
710
|
+
- The derivation block is now evaluated in context of a `Shrine::Derivation`
|
711
|
+
instance.
|
712
|
+
|
713
|
+
- The derivation block can now return only `File` and `Tempfile` objects.
|
714
|
+
|
715
|
+
- The `:download_errors` option has been removed, as it's now obsolete.
|
716
|
+
|
717
|
+
- The `:include_uploaded_file` option has been removed, as it's now obsolete.
|
718
|
+
|
719
|
+
- The source `UploadedFile` is not passed to the derivation block anymore
|
720
|
+
on `download: false`.
|
721
|
+
|
722
|
+
- The `Derivation#upload` method now closes the uploaded file.
|
723
|
+
|
724
|
+
- Uploader deleting the uploaded derivative isn't supported anymore (e.g.
|
725
|
+
`delete_raw` plugin).
|
726
|
+
|
727
|
+
- The `derivation.upload` instrumentation event payload now includes only
|
728
|
+
`:derivation` key.
|
729
|
+
|
730
|
+
* `download_endpoint`
|
731
|
+
|
732
|
+
- Support for legacy `/:storage/:id` URLs has been dropped.
|
733
|
+
|
734
|
+
- The `:storages` plugin option has been removed.
|
735
|
+
|
736
|
+
- The `Shrine::Plugins::DownloadEndpoint::App` constant has been removed.
|
737
|
+
|
738
|
+
* `data_uri`
|
739
|
+
|
740
|
+
- The deprecated `:filename` plugin option has been removed.
|
741
|
+
|
742
|
+
- The deprecated `Shrine::Plugins::DataUri::DataFile` constant has been
|
743
|
+
removed.
|
744
|
+
|
745
|
+
* `rack_file`
|
746
|
+
|
747
|
+
- The deprecated `Shrine::Plugins::RackFile::UploadedFile` constant has been
|
748
|
+
removed.
|
749
|
+
|
750
|
+
- Passing a Rack uploaded file hash to `Shrine#upload` is not supported
|
751
|
+
anymore.
|
752
|
+
|
753
|
+
* `cached_attachment_data`
|
754
|
+
|
755
|
+
- The `#<name>_cached_data=` model method has been removed.
|
756
|
+
|
757
|
+
- The `Attacher#read_cached` method has been renamed to
|
758
|
+
`Attacher#cached_data`.
|
759
|
+
|
760
|
+
* `default_url`
|
761
|
+
|
762
|
+
- Passing a block when loading the plugin is not supported anymore.
|
763
|
+
|
764
|
+
* `determine_mime_type`
|
765
|
+
|
766
|
+
- The deprecated `:default` analyzer alias has been removed.
|
767
|
+
|
768
|
+
- The private `Shrine#mime_type_analyzers` method has been removed.
|
769
|
+
|
770
|
+
* `store_dimensions`
|
771
|
+
|
772
|
+
- Failing to extract dimensions now prints out a warning by default.
|
773
|
+
|
774
|
+
- The private `Shrine#extract_dimensions` and `Shrine#dimensions_analyzers`
|
775
|
+
methods have been removed.
|
776
|
+
|
777
|
+
* `infer_extension`
|
778
|
+
|
779
|
+
- The `:mini_mime` inferrer is now the default inferrer, which requires the
|
780
|
+
`mini_mime` gem.
|
781
|
+
|
782
|
+
- The private `Shrine#infer_extension` method has been removed.
|
783
|
+
|
784
|
+
* `validation_helpers`
|
785
|
+
|
786
|
+
- The width & height validators will now raise an exception if `width` or
|
787
|
+
`height` metadata is missing.
|
788
|
+
|
789
|
+
- Support for regexes has been dropped for MIME type and extension
|
790
|
+
validators.
|
791
|
+
|
792
|
+
* `versions`
|
793
|
+
|
794
|
+
- The deprecated `:version_names`, `Shrine.version_names` and
|
795
|
+
`Shrine.version?` have been removed from `versions` plugin.
|
796
|
+
|
797
|
+
* `keep_files`
|
798
|
+
|
799
|
+
- The plugin will now always prevent deletion of both replaced and destroyed
|
800
|
+
attachments. The `:replaced` and `:destroyed` options don't have effect
|
801
|
+
anymore.
|
802
|
+
|
803
|
+
* `dynamic_storage`
|
804
|
+
|
805
|
+
- The `Shrine.dynamic_storages` method has been removed.
|
806
|
+
|
807
|
+
* `instrumentation`
|
808
|
+
|
809
|
+
- The `:location`, `:upload_options`, and `:metadata` keys have been removed
|
810
|
+
from `:options` in `upload.shrine` event payload.
|
811
|
+
|
812
|
+
- The `:metadata` key has been removed from `metadata.shrine` event payload.
|
813
|
+
|
814
|
+
* `default_storage`
|
815
|
+
|
816
|
+
- Passing `record` & `name` arguments to the storage block has been
|
817
|
+
deprecated over evaluating the block in context of the attacher instance.
|
818
|
+
|
819
|
+
* `sequel`
|
820
|
+
|
821
|
+
- The `:callbacks` plugin option has been renamed to `:hooks`.
|
822
|
+
|
823
|
+
[derivatives]: /doc/plugins/derivatives.md#readme
|
824
|
+
[versions]: /doc/plugins/versions.md#readme
|
825
|
+
[backgrounding]: /doc/plugins/backgrounding.md#readme
|
826
|
+
[shrine-memory]: https://github.com/shrinerb/shrine-memory
|
827
|
+
[atomic_helpers]: /doc/plugins/atomic_helpers.md#readme
|
828
|
+
[attacher]: /doc/attacher.md#readme
|
829
|
+
[column]: /doc/plugins/column.md#readme
|
830
|
+
[entity]: /doc/plugins/entity.md#readme
|
831
|
+
[model]: /doc/plugins/model.md#readme
|
832
|
+
[persistence]: /doc/plugins/persistence.md#readme
|
833
|
+
[mirroring]: /doc/plugins/mirroring.md#readme
|
834
|
+
[form_assign]: /doc/plugins/form_assign.md#readme
|
835
|
+
[Upgrading to Shrine 3.x]: /doc/upgrading_to_3.md#readme
|