shrine 2.19.3 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +523 -41
- data/LICENSE.txt +1 -1
- data/README.md +83 -979
- data/doc/advantages.md +231 -204
- data/doc/attacher.md +304 -153
- data/doc/carrierwave.md +297 -226
- data/doc/changing_derivatives.md +308 -0
- data/doc/changing_location.md +103 -21
- data/doc/changing_storage.md +110 -0
- data/doc/creating_persistence_plugins.md +132 -0
- data/doc/creating_plugins.md +43 -23
- data/doc/creating_storages.md +19 -5
- data/doc/design.md +147 -97
- data/doc/direct_s3.md +38 -28
- data/doc/external/articles.md +63 -0
- data/doc/external/extensions.md +53 -0
- data/doc/external/misc.md +32 -0
- data/doc/getting_started.md +1156 -0
- data/doc/metadata.md +190 -109
- data/doc/multiple_files.md +93 -30
- data/doc/paperclip.md +384 -262
- data/doc/plugins/activerecord.md +177 -46
- data/doc/plugins/add_metadata.md +139 -38
- data/doc/plugins/atomic_helpers.md +217 -0
- data/doc/plugins/backgrounding.md +156 -98
- data/doc/plugins/cached_attachment_data.md +7 -5
- data/doc/plugins/column.md +121 -0
- data/doc/plugins/data_uri.md +23 -22
- data/doc/plugins/default_storage.md +36 -10
- data/doc/plugins/default_url.md +30 -13
- data/doc/plugins/delete_raw.md +4 -2
- data/doc/plugins/derivation_endpoint.md +186 -101
- data/doc/plugins/derivatives.md +839 -0
- data/doc/plugins/determine_mime_type.md +4 -2
- data/doc/plugins/download_endpoint.md +64 -8
- data/doc/plugins/dynamic_storage.md +5 -3
- data/doc/plugins/entity.md +263 -0
- data/doc/plugins/form_assign.md +55 -0
- data/doc/plugins/included.md +31 -8
- data/doc/plugins/infer_extension.md +21 -10
- data/doc/plugins/instrumentation.md +38 -16
- data/doc/plugins/keep_files.md +16 -17
- data/doc/plugins/metadata_attributes.md +42 -13
- data/doc/plugins/mirroring.md +118 -0
- data/doc/plugins/model.md +210 -0
- data/doc/plugins/module_include.md +4 -2
- data/doc/plugins/multi_cache.md +24 -0
- data/doc/plugins/persistence.md +101 -0
- data/doc/plugins/presign_endpoint.md +9 -4
- data/doc/plugins/pretty_location.md +16 -3
- data/doc/plugins/processing.md +4 -2
- data/doc/plugins/rack_file.md +8 -2
- data/doc/plugins/rack_response.md +6 -2
- data/doc/plugins/recache.md +4 -2
- data/doc/plugins/refresh_metadata.md +49 -9
- data/doc/plugins/remote_url.md +84 -47
- data/doc/plugins/remove_attachment.md +27 -6
- data/doc/plugins/remove_invalid.md +21 -6
- data/doc/plugins/restore_cached_data.md +11 -3
- data/doc/plugins/sequel.md +159 -35
- data/doc/plugins/signature.md +16 -5
- data/doc/plugins/store_dimensions.md +14 -2
- data/doc/plugins/tempfile.md +4 -2
- data/doc/plugins/type_predicates.md +96 -0
- data/doc/plugins/upload_endpoint.md +13 -13
- data/doc/plugins/upload_options.md +6 -4
- data/doc/plugins/{default_url_options.md → url_options.md} +9 -7
- data/doc/plugins/validation.md +97 -0
- data/doc/plugins/validation_helpers.md +16 -13
- data/doc/plugins/versions.md +15 -19
- data/doc/processing.md +438 -221
- data/doc/refile.md +188 -170
- data/doc/release_notes/1.0.0.md +4 -0
- data/doc/release_notes/1.1.0.md +6 -2
- data/doc/release_notes/1.2.0.md +4 -0
- data/doc/release_notes/1.3.0.md +4 -0
- data/doc/release_notes/1.4.0.md +4 -0
- data/doc/release_notes/1.4.1.md +4 -0
- data/doc/release_notes/1.4.2.md +4 -0
- data/doc/release_notes/2.0.0.md +4 -0
- data/doc/release_notes/2.0.1.md +4 -0
- data/doc/release_notes/2.1.0.md +5 -1
- data/doc/release_notes/2.1.1.md +4 -0
- data/doc/release_notes/2.10.0.md +4 -0
- data/doc/release_notes/2.10.1.md +4 -0
- data/doc/release_notes/2.11.0.md +4 -0
- data/doc/release_notes/2.12.0.md +4 -0
- data/doc/release_notes/2.13.0.md +4 -0
- data/doc/release_notes/2.14.0.md +5 -1
- data/doc/release_notes/2.15.0.md +11 -7
- data/doc/release_notes/2.16.0.md +4 -0
- data/doc/release_notes/2.17.0.md +4 -0
- data/doc/release_notes/2.18.0.md +4 -0
- data/doc/release_notes/2.19.0.md +6 -3
- data/doc/release_notes/2.2.0.md +4 -0
- data/doc/release_notes/2.3.0.md +4 -0
- data/doc/release_notes/2.3.1.md +4 -0
- data/doc/release_notes/2.4.0.md +4 -0
- data/doc/release_notes/2.4.1.md +4 -0
- data/doc/release_notes/2.5.0.md +4 -0
- data/doc/release_notes/2.6.0.md +4 -0
- data/doc/release_notes/2.6.1.md +4 -0
- data/doc/release_notes/2.7.0.md +4 -0
- data/doc/release_notes/2.8.0.md +4 -0
- data/doc/release_notes/2.9.0.md +4 -0
- data/doc/release_notes/3.0.0.md +981 -0
- data/doc/release_notes/3.0.1.md +22 -0
- data/doc/release_notes/3.1.0.md +73 -0
- data/doc/release_notes/3.2.0.md +96 -0
- data/doc/release_notes/3.2.1.md +31 -0
- data/doc/release_notes/3.2.2.md +14 -0
- data/doc/release_notes/3.3.0.md +105 -0
- data/doc/release_notes/3.4.0.md +35 -0
- data/doc/release_notes/3.5.0.md +63 -0
- data/doc/release_notes/3.6.0.md +23 -0
- data/doc/retrieving_uploads.md +5 -2
- data/doc/securing_uploads.md +60 -37
- data/doc/storage/file_system.md +20 -3
- data/doc/storage/memory.md +19 -0
- data/doc/storage/s3.md +122 -78
- data/doc/testing.md +141 -133
- data/doc/upgrading_to_3.md +708 -0
- data/doc/validation.md +54 -90
- data/lib/shrine/attacher.rb +292 -169
- data/lib/shrine/attachment.rb +13 -46
- data/lib/shrine/plugins/_persistence.rb +93 -0
- data/lib/shrine/plugins/activerecord.rb +77 -34
- data/lib/shrine/plugins/add_metadata.rb +25 -17
- data/lib/shrine/plugins/atomic_helpers.rb +119 -0
- data/lib/shrine/plugins/backgrounding.rb +77 -113
- data/lib/shrine/plugins/cached_attachment_data.rb +6 -15
- data/lib/shrine/plugins/column.rb +102 -0
- data/lib/shrine/plugins/data_uri.rb +38 -36
- data/lib/shrine/plugins/default_storage.rb +45 -15
- data/lib/shrine/plugins/default_url.rb +12 -24
- data/lib/shrine/plugins/default_url_options.rb +3 -30
- data/lib/shrine/plugins/delete_raw.rb +10 -16
- data/lib/shrine/plugins/derivation_endpoint.rb +130 -171
- data/lib/shrine/plugins/derivatives.rb +645 -0
- data/lib/shrine/plugins/determine_mime_type.rb +9 -21
- data/lib/shrine/plugins/download_endpoint.rb +118 -133
- data/lib/shrine/plugins/dynamic_storage.rb +5 -11
- data/lib/shrine/plugins/entity.rb +158 -0
- data/lib/shrine/plugins/form_assign.rb +108 -0
- data/lib/shrine/plugins/included.rb +6 -6
- data/lib/shrine/plugins/infer_extension.rb +17 -20
- data/lib/shrine/plugins/instrumentation.rb +59 -43
- data/lib/shrine/plugins/keep_files.rb +3 -15
- data/lib/shrine/plugins/metadata_attributes.rb +28 -19
- data/lib/shrine/plugins/mirroring.rb +142 -0
- data/lib/shrine/plugins/model.rb +160 -0
- data/lib/shrine/plugins/module_include.rb +3 -3
- data/lib/shrine/plugins/multi_cache.rb +27 -0
- data/lib/shrine/plugins/presign_endpoint.rb +27 -28
- data/lib/shrine/plugins/pretty_location.rb +15 -9
- data/lib/shrine/plugins/processing.rb +22 -9
- data/lib/shrine/plugins/rack_file.rb +2 -42
- data/lib/shrine/plugins/rack_response.rb +21 -10
- data/lib/shrine/plugins/recache.rb +6 -5
- data/lib/shrine/plugins/refresh_metadata.rb +13 -11
- data/lib/shrine/plugins/remote_url.rb +49 -49
- data/lib/shrine/plugins/remove_attachment.rb +12 -6
- data/lib/shrine/plugins/remove_invalid.rb +19 -8
- data/lib/shrine/plugins/restore_cached_data.rb +13 -7
- data/lib/shrine/plugins/sequel.rb +86 -36
- data/lib/shrine/plugins/signature.rb +10 -16
- data/lib/shrine/plugins/store_dimensions.rb +35 -40
- data/lib/shrine/plugins/tempfile.rb +1 -3
- data/lib/shrine/plugins/type_predicates.rb +113 -0
- data/lib/shrine/plugins/upload_endpoint.rb +28 -24
- data/lib/shrine/plugins/upload_options.rb +14 -15
- data/lib/shrine/plugins/url_options.rb +31 -0
- data/lib/shrine/plugins/validation.rb +80 -0
- data/lib/shrine/plugins/validation_helpers.rb +35 -58
- data/lib/shrine/plugins/versions.rb +107 -87
- data/lib/shrine/plugins.rb +22 -0
- data/lib/shrine/storage/file_system.rb +46 -64
- data/lib/shrine/storage/linter.rb +42 -7
- data/lib/shrine/storage/memory.rb +49 -0
- data/lib/shrine/storage/s3.rb +173 -160
- data/lib/shrine/uploaded_file.rb +32 -32
- data/lib/shrine/version.rb +3 -3
- data/lib/shrine.rb +87 -150
- data/shrine.gemspec +11 -12
- metadata +92 -82
- data/doc/migrating_storage.md +0 -76
- data/doc/plugins/backup.md +0 -31
- data/doc/plugins/copy.md +0 -24
- data/doc/plugins/delete_promoted.md +0 -12
- data/doc/plugins/direct_upload.md +0 -172
- data/doc/plugins/hooks.md +0 -58
- data/doc/plugins/logging.md +0 -42
- data/doc/plugins/migration_helpers.md +0 -60
- data/doc/plugins/moving.md +0 -19
- data/doc/plugins/multi_delete.md +0 -20
- data/doc/plugins/parallelize.md +0 -16
- data/doc/plugins/parsed_json.md +0 -23
- data/doc/regenerating_versions.md +0 -143
- data/lib/shrine/plugins/background_helpers.rb +0 -5
- data/lib/shrine/plugins/backup.rb +0 -90
- data/lib/shrine/plugins/copy.rb +0 -50
- data/lib/shrine/plugins/delete_promoted.rb +0 -20
- data/lib/shrine/plugins/direct_upload.rb +0 -217
- data/lib/shrine/plugins/hooks.rb +0 -90
- data/lib/shrine/plugins/logging.rb +0 -142
- data/lib/shrine/plugins/migration_helpers.rb +0 -70
- data/lib/shrine/plugins/moving.rb +0 -57
- data/lib/shrine/plugins/multi_delete.rb +0 -32
- data/lib/shrine/plugins/parallelize.rb +0 -78
- data/lib/shrine/plugins/parsed_json.rb +0 -29
|
@@ -0,0 +1,981 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Shrine 3.0.0
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
This guide covers all the changes in the 3.0.0 version of Shrine. If you're
|
|
6
|
+
currently using Shrine 2.x, see **[Upgrading to Shrine 3.x]** for instructions
|
|
7
|
+
on how to upgrade.
|
|
8
|
+
|
|
9
|
+
## Major features
|
|
10
|
+
|
|
11
|
+
### Derivatives
|
|
12
|
+
|
|
13
|
+
The new **[`derivatives`][derivatives]** plugin has been added for storing
|
|
14
|
+
additional processed files alongside the main file.
|
|
15
|
+
|
|
16
|
+
```rb
|
|
17
|
+
Shrine.plugin :derivatives
|
|
18
|
+
```
|
|
19
|
+
```rb
|
|
20
|
+
class ImageUploader < Shrine
|
|
21
|
+
Attacher.derivatives_processor do |original|
|
|
22
|
+
magick = ImageProcessing::MiniMagick.source(original)
|
|
23
|
+
|
|
24
|
+
{
|
|
25
|
+
large: magick.resize_to_limit!(800, 800),
|
|
26
|
+
medium: magick.resize_to_limit!(500, 500),
|
|
27
|
+
small: magick.resize_to_limit!(300, 300),
|
|
28
|
+
}
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
```
|
|
32
|
+
```rb
|
|
33
|
+
photo = Photo.new(photo_params)
|
|
34
|
+
photo.image_derivatives! # creates derivatives
|
|
35
|
+
photo.save
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
This is a rewrite of the [`versions`][versions] plugin, bringing numerous
|
|
39
|
+
improvements:
|
|
40
|
+
|
|
41
|
+
* processed files are separated from the main file
|
|
42
|
+
|
|
43
|
+
```rb
|
|
44
|
+
photo.image_data #=>
|
|
45
|
+
# {
|
|
46
|
+
# "id": "original.jpg",
|
|
47
|
+
# "storage": "store",
|
|
48
|
+
# "metadata": { ... },
|
|
49
|
+
# "derivatives": {
|
|
50
|
+
# "large": { "id": "large.jpg", "storage": "store", "metadata": { ... } },
|
|
51
|
+
# "medium": { "id": "medium.jpg", "storage": "store", "metadata": { ... } },
|
|
52
|
+
# "small": { "id": "small.jpg", "storage": "store", "metadata": { ... } }
|
|
53
|
+
# }
|
|
54
|
+
# }
|
|
55
|
+
|
|
56
|
+
photo.image #=> #<Shrine::UploadedFile id="original.jpg" ...>
|
|
57
|
+
photo.image_derivatives #=>
|
|
58
|
+
# {
|
|
59
|
+
# large: #<Shrine::UploadedFile id="large.jpg" ...>,
|
|
60
|
+
# medium: #<Shrine::UploadedFile id="medium.jpg" ...>,
|
|
61
|
+
# small: #<Shrine::UploadedFile id="small.jpg" ...>,
|
|
62
|
+
# }
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
* processing is decoupled from promotion
|
|
66
|
+
|
|
67
|
+
```rb
|
|
68
|
+
photo = Photo.create(image: file) # promote original file to permanent storage
|
|
69
|
+
photo.image_derivatives! # generate derivatives after promotion
|
|
70
|
+
photo.save # save derivatives data
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
- ability to add or remove processed files at any point
|
|
74
|
+
|
|
75
|
+
```rb
|
|
76
|
+
class ImageUploader < Shrine
|
|
77
|
+
Attacher.derivatives_processor :thumbnails do |original|
|
|
78
|
+
# ...
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
Attacher.derivatives_processor :crop do |original, left:, top:, width:, height:|
|
|
82
|
+
vips = ImageProcessing::Vips.source(original)
|
|
83
|
+
|
|
84
|
+
{ cropped: vips.crop!(left, top, width, height) }
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
```
|
|
88
|
+
```rb
|
|
89
|
+
photo.image_derivatives!(:thumbnails)
|
|
90
|
+
photo.image_derivatives #=> { large: ..., medium: ..., small: ... }
|
|
91
|
+
photo.save
|
|
92
|
+
|
|
93
|
+
# ... sometime later ...
|
|
94
|
+
|
|
95
|
+
photo.image_derivatives!(:crop, left: 0, top: 0, width: 300, height: 300)
|
|
96
|
+
photo.image_derivatives #=> { large: ..., medium: ..., small: ..., cropped: ... }
|
|
97
|
+
photo.save
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
* possibility of uploading processed files to different storage
|
|
101
|
+
|
|
102
|
+
```rb
|
|
103
|
+
class ImageUploader < Shrine
|
|
104
|
+
# specify storage for all derivatives
|
|
105
|
+
Attacher.derivatives_storage :other_store
|
|
106
|
+
|
|
107
|
+
# or specify storage per derivative
|
|
108
|
+
Attacher.derivatives_storage { |derivative| :other_store }
|
|
109
|
+
end
|
|
110
|
+
```
|
|
111
|
+
```rb
|
|
112
|
+
photo = Photo.create(image: file)
|
|
113
|
+
photo.image.storage_key #=> :store
|
|
114
|
+
|
|
115
|
+
photo.image_derivatives!
|
|
116
|
+
photo.image_derivatives[:large].storage_key #=> :other_store
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Attacher redesign
|
|
120
|
+
|
|
121
|
+
The [`Shrine::Attacher`][attacher] class has been rewritten and can now be
|
|
122
|
+
used without models:
|
|
123
|
+
|
|
124
|
+
```rb
|
|
125
|
+
attacher = Shrine::Attacher.new
|
|
126
|
+
attacher.attach(file)
|
|
127
|
+
attacher.file #=> #<Shrine::UploadedFile>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The `Attacher#data`, `Attacher#load_data`, and `Attacher.from_data` methods
|
|
131
|
+
have been added for dumping and loading the attached file:
|
|
132
|
+
|
|
133
|
+
```rb
|
|
134
|
+
# dump attached file into a serializable Hash
|
|
135
|
+
data = attacher.data #=> { "id" => "abc123.jpg", "storage" => "store", "metadata" => { ... } }
|
|
136
|
+
```
|
|
137
|
+
```rb
|
|
138
|
+
# initialize attacher from attached file data...
|
|
139
|
+
attacher = Shrine::Attacher.from_data(data)
|
|
140
|
+
attacher.file #=> #<Shrine::UploadedFile id="abc123.jpg" storage=:store metadata={...}>
|
|
141
|
+
|
|
142
|
+
# ...or load attached file into an existing attacher
|
|
143
|
+
attacher = Shrine::Attacher.new
|
|
144
|
+
attacher.load_data(data)
|
|
145
|
+
attacher.file #=> #<Shrine::UploadedFile>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Several more methods have been added:
|
|
149
|
+
|
|
150
|
+
- `Attacher#attach` – attaches the file directly to permanent storage
|
|
151
|
+
- `Attacher#attach_cached` – extracted from `Attacher#assign`
|
|
152
|
+
- `Attacher#upload` – calls `Shrine#upload`, passing `:record` and `:name` context
|
|
153
|
+
- `Attacher#file` – alias for `Attacher#get`
|
|
154
|
+
- `Attacher#cache_key` – returns temporary storage key (`:cache` by default)
|
|
155
|
+
- `Attacher#store_key` – returns permanent storage key (`:store` by default)
|
|
156
|
+
|
|
157
|
+
#### Column
|
|
158
|
+
|
|
159
|
+
The new [`column`][column] plugin adds the ability to serialize attached file
|
|
160
|
+
data, in format suitable for writing into a database column.
|
|
161
|
+
|
|
162
|
+
```rb
|
|
163
|
+
Shrine.plugin :column
|
|
164
|
+
```
|
|
165
|
+
```rb
|
|
166
|
+
# dump attached file data into a JSON string
|
|
167
|
+
data = attacher.column_data #=> '{"id":"abc123.jpg","storage":"store","metadata":{...}}'
|
|
168
|
+
```
|
|
169
|
+
```rb
|
|
170
|
+
# initialize attacher from attached file data...
|
|
171
|
+
attacher = Shrine::Attacher.from_column(data)
|
|
172
|
+
attacher.file #=> #<Shrine::UploadedFile id="abc123.jpg" storage=:store metadata={...}>
|
|
173
|
+
|
|
174
|
+
# ...or load attached file into an existing attacher
|
|
175
|
+
attacher = Shrine::Attacher.new
|
|
176
|
+
attacher.load_column(data)
|
|
177
|
+
attacher.file #=> #<Shrine::UploadedFile>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### Entity
|
|
181
|
+
|
|
182
|
+
The new [`entity`][entity] plugin adds support for immutable structs, which
|
|
183
|
+
are commonly used with ROM, Hanami and dry-rb.
|
|
184
|
+
|
|
185
|
+
```rb
|
|
186
|
+
Shrine.plugin :entity
|
|
187
|
+
```
|
|
188
|
+
```rb
|
|
189
|
+
class Photo < Hanami::Entity
|
|
190
|
+
include Shrine::Attachment(:image)
|
|
191
|
+
end
|
|
192
|
+
```
|
|
193
|
+
```rb
|
|
194
|
+
photo = Photo.new(image_data: '{"id":"abc123.jpg","storage":"store","metadata":{...}}')
|
|
195
|
+
photo.image #=> #<Shrine::UploadedFile id="abc123.jpg" storage=:store ...>
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
#### Model
|
|
199
|
+
|
|
200
|
+
The new [`model`][model] plugin adds support for mutable structs, which is
|
|
201
|
+
used by `activerecord` and `sequel` plugins.
|
|
202
|
+
|
|
203
|
+
```rb
|
|
204
|
+
Shrine.plugin :model
|
|
205
|
+
```
|
|
206
|
+
```rb
|
|
207
|
+
class Photo < Struct.new(:image_data)
|
|
208
|
+
include Shrine::Attachment(:image)
|
|
209
|
+
end
|
|
210
|
+
```
|
|
211
|
+
```rb
|
|
212
|
+
photo = Photo.new
|
|
213
|
+
photo.image = file
|
|
214
|
+
photo.image #=> #<Shrine::UploadedFile id="abc123.jpg" storage=:cache ...>
|
|
215
|
+
photo.image_data #=> #=> '{"id":"abc123.jpg", "storage":"cache", "metadata":{...}}'
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Backgrounding rewrite
|
|
219
|
+
|
|
220
|
+
* The [`backgrounding`][backgrounding] plugin has been rewritten for more
|
|
221
|
+
flexibility and simplicity. The new usage is much more explicit:
|
|
222
|
+
|
|
223
|
+
```rb
|
|
224
|
+
Shrine.plugin :backgrounding
|
|
225
|
+
Shrine::Attacher.promote_block do
|
|
226
|
+
PromoteJob.perform_async(self.class.name, record.class.name, record.id, name, file_data)
|
|
227
|
+
end
|
|
228
|
+
Shrine::Attacher.destroy_block do
|
|
229
|
+
DestroyJob.perform_async(self.class.name, data)
|
|
230
|
+
end
|
|
231
|
+
```
|
|
232
|
+
```rb
|
|
233
|
+
class PromoteJob
|
|
234
|
+
include Sidekiq::Worker
|
|
235
|
+
|
|
236
|
+
def perform(attacher_class, record_class, record.id, name, file_data)
|
|
237
|
+
attacher_class = Object.const_get(attacher_class)
|
|
238
|
+
record = Object.const_get(record_class).find(record_id) # if using Active Record
|
|
239
|
+
|
|
240
|
+
attacher = attacher_class.retrieve(model: record, name: name, file: file_data)
|
|
241
|
+
attacher.atomic_promote
|
|
242
|
+
rescue Shrine::AttachmentChanged, ActiveRecord::RecordNotFound
|
|
243
|
+
# attachment has changed or the record has been deleted, nothing to do
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
```
|
|
247
|
+
```rb
|
|
248
|
+
class DestroyJob
|
|
249
|
+
include Sidekiq::Worker
|
|
250
|
+
|
|
251
|
+
def perform(attacher_class, data)
|
|
252
|
+
attacher_class = Object.const_get(attacher_class)
|
|
253
|
+
|
|
254
|
+
attacher = attacher_class.from_data(data)
|
|
255
|
+
attacher.destroy
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
There are several main differences compared to the old implementation:
|
|
261
|
+
|
|
262
|
+
- we are in charge of passing the record to the background job
|
|
263
|
+
- we can access the attacher before promotion
|
|
264
|
+
- we can react to errors that caused promotion to abort
|
|
265
|
+
|
|
266
|
+
We can now also register backgrounding hooks on an attacher instance, allowing
|
|
267
|
+
us to pass additional parameters to the background job:
|
|
268
|
+
|
|
269
|
+
```rb
|
|
270
|
+
photo = Photo.new(photo_params)
|
|
271
|
+
|
|
272
|
+
photo.image_attacher.promote_block do |attacher|
|
|
273
|
+
PromoteJob.perform_async(
|
|
274
|
+
attacher.class.name,
|
|
275
|
+
attacher.record.class.name,
|
|
276
|
+
attacher.record.id,
|
|
277
|
+
attacher.name,
|
|
278
|
+
attacher.file_data,
|
|
279
|
+
current_user.id, # <== parameters from the controller
|
|
280
|
+
)
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
photo.save # will call our instance-level backgrounding hook
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Persistence interface
|
|
287
|
+
|
|
288
|
+
The persistence plugins (`activerecord`, `sequel`) now implement a unified
|
|
289
|
+
[persistence] interface:
|
|
290
|
+
|
|
291
|
+
| Method | Description |
|
|
292
|
+
| :----------------- | :---------- |
|
|
293
|
+
| `Attacher#persist` | persists attachment data |
|
|
294
|
+
| `Attacher#atomic_persist` | persists attachment data if attachment hasn’t changed |
|
|
295
|
+
| `Attacher#atomic_promote` | promotes cached file and atomically persists changes |
|
|
296
|
+
|
|
297
|
+
The "atomic" methods use the new [`atomic_helpers`][atomic_helpers] plugin,
|
|
298
|
+
and are useful for background jobs. For example, this is how we'd use them to
|
|
299
|
+
implement metadata extraction in the background in a concurrency-safe way:
|
|
300
|
+
|
|
301
|
+
```rb
|
|
302
|
+
MetadataJob.perform_async(
|
|
303
|
+
attacher.class.name,
|
|
304
|
+
attacher.record.class.name,
|
|
305
|
+
attacher.record.id,
|
|
306
|
+
attacher.name,
|
|
307
|
+
attacher.file_data,
|
|
308
|
+
)
|
|
309
|
+
```
|
|
310
|
+
```rb
|
|
311
|
+
class MetadataJob
|
|
312
|
+
include Sidekiq::Worker
|
|
313
|
+
|
|
314
|
+
def perform(attacher_class, record_class, record_id, name, file_data)
|
|
315
|
+
attacher_class = Object.const_get(attacher_class)
|
|
316
|
+
record = Object.const_get(record_class).find(record_id) # if using Active Record
|
|
317
|
+
|
|
318
|
+
attacher = attacher_class.retrieve(model: record, name: name, file: file_data)
|
|
319
|
+
attacher.refresh_metadata! # extract metadata
|
|
320
|
+
attacher.atomic_persist # persist if attachment hasn't changed
|
|
321
|
+
rescue Shrine::AttachmentChanged, ActiveRecord::RecordNotFound
|
|
322
|
+
# attachment has changed or record has been deleted, nothing to do
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
## Other new plugins
|
|
328
|
+
|
|
329
|
+
* The new [`mirroring`][mirroring] plugin has been added for replicating
|
|
330
|
+
uploads and deletes to other storages.
|
|
331
|
+
|
|
332
|
+
```rb
|
|
333
|
+
Shrine.storages = { cache: ..., store: ..., backup: ... }
|
|
334
|
+
|
|
335
|
+
Shrine.plugin :mirroring, mirror: { store: :backup }
|
|
336
|
+
```
|
|
337
|
+
```rb
|
|
338
|
+
file = Shrine.upload(io, :store) # uploads to :store and :backup
|
|
339
|
+
file.delete # deletes from :store and :backup
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
* The new [`multi_cache`][multi_cache] plugin has been added for allowing an
|
|
343
|
+
attacher to accept files from additional temporary storages.
|
|
344
|
+
|
|
345
|
+
```rb
|
|
346
|
+
Shrine.storages = { cache: ..., cache_one: ..., cache_two: ..., store: ... }
|
|
347
|
+
|
|
348
|
+
Shrine.plugin :multi_cache, additional_cache: [:cache_one, :cache_two]
|
|
349
|
+
```
|
|
350
|
+
```rb
|
|
351
|
+
photo.image = { "id" => "...", "storage" => "cache", "metadata" => { ... } }
|
|
352
|
+
photo.image.storage_key #=> :cache
|
|
353
|
+
# or
|
|
354
|
+
photo.image = { "id" => "...", "storage" => "cache_one", "metadata" => { ... } }
|
|
355
|
+
photo.image.storage_key #=> :cache_one
|
|
356
|
+
# or
|
|
357
|
+
photo.image = { "id" => "...", "storage" => "cache_two", "metadata" => { ... } }
|
|
358
|
+
photo.image.storage_key #=> :cache_two
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
* The new [`form_assign`][form_assign] plugin has been added for assigning
|
|
362
|
+
files directly from form params.
|
|
363
|
+
|
|
364
|
+
```rb
|
|
365
|
+
Shrine.plugin :form_assign
|
|
366
|
+
```
|
|
367
|
+
```rb
|
|
368
|
+
attacher = photo.image_attacher
|
|
369
|
+
attacher.form_assign({ "image" => file, "title" => "...", "description" => "..." })
|
|
370
|
+
attacher.file #=> #<Shrine::UploadedFile id="..." storage=:cache ...>
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## Other features
|
|
374
|
+
|
|
375
|
+
* Model file assignment can now be configured to upload directly to permanent
|
|
376
|
+
storage.
|
|
377
|
+
|
|
378
|
+
```rb
|
|
379
|
+
Shrine.plugin :model, cache: false
|
|
380
|
+
```
|
|
381
|
+
```rb
|
|
382
|
+
photo.image = file
|
|
383
|
+
photo.image.storage_key #=> :store (permanent storage)
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
* New `Shrine.download_response` method has been added to the
|
|
387
|
+
`download_endpoint` plugin for generating file response from the controller.
|
|
388
|
+
|
|
389
|
+
```rb
|
|
390
|
+
Rails.application.routes.draw do
|
|
391
|
+
get "/attachments" => "files#download"
|
|
392
|
+
end
|
|
393
|
+
```
|
|
394
|
+
```rb
|
|
395
|
+
class FilesController < ApplicationController
|
|
396
|
+
def download
|
|
397
|
+
# ... we can now perform things like authentication here ...
|
|
398
|
+
set_rack_response Shrine.download_response(env)
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
private
|
|
402
|
+
|
|
403
|
+
def set_rack_response((status, headers, body))
|
|
404
|
+
self.status = status
|
|
405
|
+
self.headers.merge!(headers)
|
|
406
|
+
self.response_body = body
|
|
407
|
+
end
|
|
408
|
+
end
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
* The `Attacher#refresh_metadata!` method has been added to `refresh_metadata`
|
|
412
|
+
plugin. It refreshes metadata and writes new attached file data back into the
|
|
413
|
+
data attribute.
|
|
414
|
+
|
|
415
|
+
```rb
|
|
416
|
+
attacher.file.refresh_metadata!
|
|
417
|
+
attacher.write
|
|
418
|
+
# can now be shortened to
|
|
419
|
+
attacher.refresh_metadata!
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
* Including a `Shrine::Attachment` module now defines a `.<name>_attacher`
|
|
423
|
+
class method on the target class.
|
|
424
|
+
|
|
425
|
+
```rb
|
|
426
|
+
class Photo
|
|
427
|
+
include ImageUploader::Attachment(:image)
|
|
428
|
+
end
|
|
429
|
+
```
|
|
430
|
+
```rb
|
|
431
|
+
Photo.image_attacher #=> #<ImageUploader::Attacher ...>
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
* The attachment data serializer is now configurable (by default `JSON`
|
|
435
|
+
standard library is used):
|
|
436
|
+
|
|
437
|
+
```rb
|
|
438
|
+
require "oj" # https://github.com/ohler55/oj
|
|
439
|
+
|
|
440
|
+
Shrine.plugin :column, serializer: Oj
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
* It's now possible to pass options to the validate block via the `:validate`
|
|
444
|
+
option:
|
|
445
|
+
|
|
446
|
+
```rb
|
|
447
|
+
attacher.assign(file, validate: { foo: "bar" })
|
|
448
|
+
```
|
|
449
|
+
```rb
|
|
450
|
+
class MyUploader < Shrine
|
|
451
|
+
Attacher.validate do |**options|
|
|
452
|
+
options #=> { foo: "bar" }
|
|
453
|
+
end
|
|
454
|
+
end
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
* Validation can now be skipped on assignment by passing `validate: false`.
|
|
458
|
+
|
|
459
|
+
```rb
|
|
460
|
+
attacher.attach(file, validate: false) # skip validation
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
* Closing the uploaded file can now be prevented by passing `close: false` to
|
|
464
|
+
`Shrine#upload`.
|
|
465
|
+
|
|
466
|
+
* Uploaded file can now be automatically deleted by passing `delete: true` to
|
|
467
|
+
`Shrine#upload`.
|
|
468
|
+
|
|
469
|
+
* New `Attacher#file!` method has been added for retrieving the attached file
|
|
470
|
+
and raising and exception if it doesn't exist.
|
|
471
|
+
|
|
472
|
+
* New `Derivation#opened` method has been added for retrieving an opened
|
|
473
|
+
derivative in `derivation_endpoint` plugin.
|
|
474
|
+
|
|
475
|
+
* New `Storage#delete_prefixed` method has been added for deleting all files
|
|
476
|
+
in specified directory.
|
|
477
|
+
|
|
478
|
+
```rb
|
|
479
|
+
storage.delete_prefixed("some_directory/")
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
## Performance improvements
|
|
483
|
+
|
|
484
|
+
* The attached file is now parsed and loaded from record column only once,
|
|
485
|
+
which can greatly improve performance if the same attached file is being
|
|
486
|
+
accessed multiple times.
|
|
487
|
+
|
|
488
|
+
```rb
|
|
489
|
+
photo = Photo.find(photo_id)
|
|
490
|
+
photo.image # parses and loads attached file
|
|
491
|
+
photo.image # returns memoized attached file
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
* The `S3#open` method doesn't perform a `#head_obect` request anymore.
|
|
495
|
+
|
|
496
|
+
* The `derivation_endpoint` plugin doesn't perform a `Storage#exists?` call
|
|
497
|
+
anymore when `:upload` is enabled.
|
|
498
|
+
|
|
499
|
+
* The `download_endpoint` plugin doesn't perform a `Storage#exists?` call
|
|
500
|
+
anymore.
|
|
501
|
+
|
|
502
|
+
## Other Improvements
|
|
503
|
+
|
|
504
|
+
### Core improvements
|
|
505
|
+
|
|
506
|
+
* Shrine now works again with MRI 2.3.
|
|
507
|
+
|
|
508
|
+
* The memory storage from the [shrine-memory] gem has been merged into core.
|
|
509
|
+
|
|
510
|
+
```rb
|
|
511
|
+
# Gemfile
|
|
512
|
+
gem "shrine-memory" # this can be removed
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
* The `Attacher#assign` method now accepts cached file data as a Hash.
|
|
516
|
+
|
|
517
|
+
```rb
|
|
518
|
+
photo.image = { "id" => "...", "storage" => "cache", "metadata" => { ... } }
|
|
519
|
+
````
|
|
520
|
+
|
|
521
|
+
* An `UploadedFile` object can now be initialized with symbol keys.
|
|
522
|
+
|
|
523
|
+
```rb
|
|
524
|
+
Shrine.uploaded_file(id: "...", storage: :store, metadata: { ... })
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
* The temporary storage doesn't need to be defined anymore if it's not used.
|
|
528
|
+
|
|
529
|
+
* Any changes to `Shrine.storages` will now be applied to existing `Shrine` and
|
|
530
|
+
`Attacher` instances.
|
|
531
|
+
|
|
532
|
+
* When copying the S3 object to another location, any specified upload options
|
|
533
|
+
will now be applied.
|
|
534
|
+
|
|
535
|
+
* Deprecation of passing unknown options to `FileSystem#open` has been
|
|
536
|
+
reverted. This allows users to continue using `FileSystem` storage in tests
|
|
537
|
+
as a mock storage.
|
|
538
|
+
|
|
539
|
+
* The `Shrine#upload` method now infers file extension from `filename` metadata,
|
|
540
|
+
making possible to use `filename` to specify file extension.
|
|
541
|
+
|
|
542
|
+
```rb
|
|
543
|
+
file = uploader.upload(StringIO.new("some text"), metadata: { "filename" => "file.txt" })
|
|
544
|
+
file.id #=> "2a2467ee6acbc5cb.txt"
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
* The `Shrine.opts` hash is now deep-copied on subclassing. This allows plugins
|
|
548
|
+
to freely mutate hashes and arrays in `Shrine.opts`, knowing they won't be
|
|
549
|
+
shared across subclasses.
|
|
550
|
+
|
|
551
|
+
* The `down` dependency has been updated to `~> 5.0`.
|
|
552
|
+
|
|
553
|
+
* The `Shrine::Attachment[]` method has been added as an alternative syntax for
|
|
554
|
+
creating attachment modules.
|
|
555
|
+
|
|
556
|
+
```rb
|
|
557
|
+
class Photo
|
|
558
|
+
include ImageUploader::Attachment[:image]
|
|
559
|
+
end
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
### Plugin improvements
|
|
563
|
+
|
|
564
|
+
* The `activerecord` plugin now works with Active Record 3.
|
|
565
|
+
|
|
566
|
+
* Callback code from `activerecord` and `sequel` plugin has been moved into
|
|
567
|
+
attacher methods, allowing the user to override them.
|
|
568
|
+
|
|
569
|
+
- `Attacher#(activerecord|sequel)_before_save`
|
|
570
|
+
- `Attacher#(activerecord|sequel)_after_save`
|
|
571
|
+
- `Attacher#(activerecord|sequel)_after_destroy`
|
|
572
|
+
|
|
573
|
+
* The `url_options` plugin now allows you to override URL options by deleting
|
|
574
|
+
them.
|
|
575
|
+
|
|
576
|
+
```rb
|
|
577
|
+
uploaded_file.url(response_content_disposition: "attachment")
|
|
578
|
+
```
|
|
579
|
+
```rb
|
|
580
|
+
plugin :url_options, store: -> (io, options) {
|
|
581
|
+
disposition = options.delete(:response_content_disposition, "inline")
|
|
582
|
+
|
|
583
|
+
{
|
|
584
|
+
response_content_disposition: ContentDisposition.format(
|
|
585
|
+
disposition: disposition,
|
|
586
|
+
filename: io.original_filename,
|
|
587
|
+
)
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
* The `:upload_options` hash passed to the uploader is now merged with any
|
|
593
|
+
options defined with the `upload_options` plugin.
|
|
594
|
+
|
|
595
|
+
* The `default_storage` now evaluates the storage block in context of the
|
|
596
|
+
`Attacher` instance.
|
|
597
|
+
|
|
598
|
+
* New `Attacher.default_cache` and `Attacher.default_store` methods have been
|
|
599
|
+
added to the `default_storage` plugin for declaratively setting default
|
|
600
|
+
storage.
|
|
601
|
+
|
|
602
|
+
```rb
|
|
603
|
+
Attacher.default_cache { ... }
|
|
604
|
+
Attacher.default_store { ... }
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
* The `derivation_endpoint` plugin now handles string derivation names.
|
|
608
|
+
|
|
609
|
+
* The `Derivation#upload` method from `derivation_endpoint` plugin now accepts
|
|
610
|
+
additional uploader options
|
|
611
|
+
|
|
612
|
+
* The `Derivation#upload` method from `derivation_endpoint` plugin now accepts
|
|
613
|
+
any IO-like object.
|
|
614
|
+
|
|
615
|
+
* The `derivation_endpoint` plugin doesn't re-open `File` objects returned in
|
|
616
|
+
derivation block anymore.
|
|
617
|
+
|
|
618
|
+
* The `instrumentation` plugin now instruments `UploadedFile#open` calls as a
|
|
619
|
+
new `open.shrine` event. `UploadedFile#download` is still instrumented as
|
|
620
|
+
`download.shrine`.
|
|
621
|
+
|
|
622
|
+
* The `upload.shrine` event now has `:metadata` on the top level in
|
|
623
|
+
`instrumentation` plugin.
|
|
624
|
+
|
|
625
|
+
* The width & height validators in `store_dimensions` plugin don't require
|
|
626
|
+
`UploadedFile#width` and `UploadedFile#height` methods to be defined anymore,
|
|
627
|
+
only that the corresponding metadata exists.
|
|
628
|
+
|
|
629
|
+
* Any options passed to `Attacher#attach_cached` are now forwarded to metadata
|
|
630
|
+
extraction when `restore_cached_data` plugin is loaded.
|
|
631
|
+
|
|
632
|
+
* The `infer_extension` plugin now works correctly with `pretty_location`
|
|
633
|
+
plugin when `pretty_location` was loaded after `infer_extension`.
|
|
634
|
+
|
|
635
|
+
* The `pretty_location` plugin now accepts `:class_underscore` option for
|
|
636
|
+
underscoring class names.
|
|
637
|
+
|
|
638
|
+
```rb
|
|
639
|
+
plugin :pretty_location
|
|
640
|
+
# "blogpost/aa357797-5845-451b-8662-08eecdc9f762/image/493g82jf23.jpg"
|
|
641
|
+
|
|
642
|
+
plugin :pretty_location, class_underscore: :true
|
|
643
|
+
# "blog_post/aa357797-5845-451b-8662-08eecdc9f762/image/493g82jf23.jpg"
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
* You can now load multiple persistence plugins simulatenously, and the correct
|
|
647
|
+
one will be activated during persistence.
|
|
648
|
+
|
|
649
|
+
## Backwards compatibility
|
|
650
|
+
|
|
651
|
+
### Plugin deprecation and removal
|
|
652
|
+
|
|
653
|
+
* The `backgrounding` plugin has been rewritten and has a new API. While the
|
|
654
|
+
new API works in a similar way, no backwards compatibility has been kept with
|
|
655
|
+
the previous API.
|
|
656
|
+
|
|
657
|
+
* The `versions`, `processing`, `recache`, and `delete_raw` plugins have been
|
|
658
|
+
deprecated in favor of the new `derivatives` plugin.
|
|
659
|
+
|
|
660
|
+
* The `module_include` plugin has been deprecated over overriding core classes
|
|
661
|
+
directly.
|
|
662
|
+
|
|
663
|
+
* The `hooks`, `parallelize`, `parsed_json`, and `delete_promoted` plugins have
|
|
664
|
+
been removed.
|
|
665
|
+
|
|
666
|
+
* The deprecated `copy`, `backup`, `multi_delete`, `moving`, `logging`,
|
|
667
|
+
`direct_upload` `background_helpers`, and `migration_helpers` plugins have
|
|
668
|
+
been removed.
|
|
669
|
+
|
|
670
|
+
* The `default_url_options` plugin has been renamed to `url_options`.
|
|
671
|
+
|
|
672
|
+
### Attacher API
|
|
673
|
+
|
|
674
|
+
* The `Attacher.new` method now only accepts a hash of options, use
|
|
675
|
+
`Attacher.from_model` for initializing from a model.
|
|
676
|
+
|
|
677
|
+
* If you're changing the attachment data column directly, you'll now need to
|
|
678
|
+
call `Attacher#reload` to make the attacher reflect those changes.
|
|
679
|
+
|
|
680
|
+
* The `Attacher#promote` method now only saves the promoted file in memory,
|
|
681
|
+
it doesn't persist the changes.
|
|
682
|
+
|
|
683
|
+
* The `Attacher#_set` and `Attacher#set` methods have been renamed to
|
|
684
|
+
`Attacher#set` and `Attacher#changed`.
|
|
685
|
+
|
|
686
|
+
* The `Attacher#cache!`, `Attacher#store!`, and `Attacher#delete!` methods have
|
|
687
|
+
been removed.
|
|
688
|
+
|
|
689
|
+
* The `Attacher#_promote` and `Attacher#_delete` methods have been removed.
|
|
690
|
+
|
|
691
|
+
* The `Attacher#swap`, `Attacher#update`, `Attacher#read`, `Attacher#write`,
|
|
692
|
+
`Attacher#convert_to_data`, `Attacher#convert_before_write`, and
|
|
693
|
+
`Attache#convert_after_read` methods have been removed.
|
|
694
|
+
|
|
695
|
+
* The `Attacher.validate`, `Attacher#validate` and `Attacher#errors` methods
|
|
696
|
+
have been extracted into the new `validation` plugin.
|
|
697
|
+
|
|
698
|
+
* The `Attacher#data_attribute` method has been renamed to `Attacher#attribute`.
|
|
699
|
+
|
|
700
|
+
* The `Attacher#replace` method has been renamed to
|
|
701
|
+
`Attacher#destroy_previous`.
|
|
702
|
+
|
|
703
|
+
* The `Attacher#assign` method now raises an exception when non-cached uploaded
|
|
704
|
+
file is assigned.
|
|
705
|
+
|
|
706
|
+
* The `Attacher#attached?` method now returns whether a file is attached,
|
|
707
|
+
regardless of whether it was changed or not.
|
|
708
|
+
|
|
709
|
+
### Attachment API
|
|
710
|
+
|
|
711
|
+
* The `Shrine::Attachment` module doesn't define any instance methods by itself
|
|
712
|
+
anymore. This has been moved into `entity` and `model` plugins.
|
|
713
|
+
|
|
714
|
+
### Uploader API
|
|
715
|
+
|
|
716
|
+
* The `:phase` option has been removed.
|
|
717
|
+
|
|
718
|
+
* The `Shrine#process` and `Shrine#processed` methods have been removed.
|
|
719
|
+
|
|
720
|
+
* The `Shrine#store`, `Shrine#_store`, `Shrine#put`, and `Shrine#copy` methods
|
|
721
|
+
have been removed.
|
|
722
|
+
|
|
723
|
+
* The `Shrine#delete`, `Shrine#_delete`, and `Shrine#remove` methods have been
|
|
724
|
+
removed.
|
|
725
|
+
|
|
726
|
+
* The `Shrine#uploaded?` method has been removed.
|
|
727
|
+
|
|
728
|
+
* The `Shrine.uploaded_file` method doesn't yield files anymore by default.
|
|
729
|
+
|
|
730
|
+
* The options for `Shrine#upload` and `Shrine#extract_metadata` are now
|
|
731
|
+
required to have symbol keys.
|
|
732
|
+
|
|
733
|
+
* The `Shrine.uploaded_file` method now raises `ArgumentError` on invalid
|
|
734
|
+
arguments.
|
|
735
|
+
|
|
736
|
+
* The `Shrine#upload` method doesn't rescue exceptions that happen in
|
|
737
|
+
`IO#close` anymore.
|
|
738
|
+
|
|
739
|
+
* The deprecated `Shrine::IO_METHODS` constant has been removed.
|
|
740
|
+
|
|
741
|
+
### Uploaded File API
|
|
742
|
+
|
|
743
|
+
* The `UploadedFile` method now extracts data from the given hash on
|
|
744
|
+
initialization, it doesn't store the whole hash anymore. This means the
|
|
745
|
+
following potential code won't work anymore:
|
|
746
|
+
|
|
747
|
+
```rb
|
|
748
|
+
uploaded_file.id #=> "foo"
|
|
749
|
+
uploaded_file.data["id"] = "bar"
|
|
750
|
+
uploaded_file.id #=> "foo"
|
|
751
|
+
```
|
|
752
|
+
|
|
753
|
+
* The `UploadedFile#storage_key` method now returns a Symbol instead of a
|
|
754
|
+
String.
|
|
755
|
+
|
|
756
|
+
```rb
|
|
757
|
+
# previous behaviour
|
|
758
|
+
uploaded_file.storage_key #=> "store"
|
|
759
|
+
|
|
760
|
+
# new behaviour
|
|
761
|
+
uploaded_file.storage_key #=> :store
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
* The `UploadedFile#==` method now requires both uploaded file objects to be
|
|
765
|
+
of the same class.
|
|
766
|
+
|
|
767
|
+
### Storage API
|
|
768
|
+
|
|
769
|
+
* The `Storage#open` method is now required to accept additional options.
|
|
770
|
+
|
|
771
|
+
```rb
|
|
772
|
+
# this won't work anymore
|
|
773
|
+
def open(id)
|
|
774
|
+
# ...
|
|
775
|
+
end
|
|
776
|
+
|
|
777
|
+
# this is now required
|
|
778
|
+
def open(id, **options)
|
|
779
|
+
# ...
|
|
780
|
+
end
|
|
781
|
+
```
|
|
782
|
+
|
|
783
|
+
* The `Storage#open` method is now required to raise `Shrine::FileNotFound`
|
|
784
|
+
exception when the file is missing.
|
|
785
|
+
|
|
786
|
+
### S3 API
|
|
787
|
+
|
|
788
|
+
* The support for `aws-sdk` 2.x and `aws-sdk-s3` < 1.14 has been removed.
|
|
789
|
+
|
|
790
|
+
* `S3#open` now raises `Shrine::FileNotFound` exception when S3 object doesn't
|
|
791
|
+
exist on the bucket.
|
|
792
|
+
|
|
793
|
+
* The `S3#upload` method will now override any S3 object data when copying
|
|
794
|
+
from another S3 object. If you were relying on S3 object data being inherited
|
|
795
|
+
on copy, you will need to update your code.
|
|
796
|
+
|
|
797
|
+
* The `:host` option in `S3#initialize` has been removed.
|
|
798
|
+
|
|
799
|
+
* The `:download` option in `S3#url` has been removed.
|
|
800
|
+
|
|
801
|
+
* Specifying `:multipart_threshold` as an integer is not supported anymore.
|
|
802
|
+
|
|
803
|
+
* Non URI-escaped `:content_disposition` and `:response_content_disposition`
|
|
804
|
+
values are not supported anymore.
|
|
805
|
+
|
|
806
|
+
* The `S3#presign` method now returns a hash instead of an object for default
|
|
807
|
+
POST method.
|
|
808
|
+
|
|
809
|
+
* The deprecated `S3#stream`, `S3#download`, and `S3#s3` methods have been
|
|
810
|
+
removed.
|
|
811
|
+
|
|
812
|
+
* The `S3#open` method doesn't include an `:object` in `Down::ChunkedIO#data`
|
|
813
|
+
anymore.
|
|
814
|
+
|
|
815
|
+
### FileSystem API
|
|
816
|
+
|
|
817
|
+
* `FileSystem#open` now raises `Shrine::FileNotFound` exception when file does
|
|
818
|
+
not exist on the filesystem.
|
|
819
|
+
|
|
820
|
+
* The deprecated `:host` option in `FileSystem#initialize` has been removed.
|
|
821
|
+
|
|
822
|
+
* The deprecated `:older_than` option in `FileSystem#clear!` has been removed.
|
|
823
|
+
|
|
824
|
+
* The deprecated `FileSystem#download` method has been removed.
|
|
825
|
+
|
|
826
|
+
* The `FileSystem#movable?` and `FileSystem#move` methods have been made
|
|
827
|
+
private.
|
|
828
|
+
|
|
829
|
+
* The `FileSystem#open` method doesn't accept a block anymore.
|
|
830
|
+
|
|
831
|
+
### Plugins API
|
|
832
|
+
|
|
833
|
+
* `remote_url`
|
|
834
|
+
|
|
835
|
+
- A custom downloader is now required to raise
|
|
836
|
+
`Shrine::Plugins::RemoteUrl::DownloadError` in order for the exception to
|
|
837
|
+
be converted into a validation error. `Down::NotFound` and `Down::TooLarge`
|
|
838
|
+
exceptions are converted by default. All other exceptions are propagated.
|
|
839
|
+
|
|
840
|
+
* `upload_endpoint`
|
|
841
|
+
|
|
842
|
+
- The deprecated `Shrine::Plugins::UploadEndpoint::App` constant has been
|
|
843
|
+
removed.
|
|
844
|
+
|
|
845
|
+
- The `:request` option holding the `Rack::Request` object isn't passed to
|
|
846
|
+
the uploader anymore.
|
|
847
|
+
|
|
848
|
+
* `presign_endpoint`
|
|
849
|
+
|
|
850
|
+
- `Storage#presign` results that cannot coerce themselves into a Hash are not
|
|
851
|
+
supported anymore.
|
|
852
|
+
|
|
853
|
+
- The deprecated `Shrine::Plugins::PresignEndpoint::App` constant has been
|
|
854
|
+
removed.
|
|
855
|
+
|
|
856
|
+
* `derivation_endpoint`
|
|
857
|
+
|
|
858
|
+
- The derivation block is now evaluated in context of a `Shrine::Derivation`
|
|
859
|
+
instance.
|
|
860
|
+
|
|
861
|
+
- The derivation block can now return only `File` and `Tempfile` objects.
|
|
862
|
+
|
|
863
|
+
- The `:download_errors` option has been removed, as it's now obsolete.
|
|
864
|
+
|
|
865
|
+
- The `:include_uploaded_file` option has been removed, as it's now obsolete.
|
|
866
|
+
|
|
867
|
+
- The source `UploadedFile` is not passed to the derivation block anymore
|
|
868
|
+
on `download: false`.
|
|
869
|
+
|
|
870
|
+
- The `Derivation#upload` method now closes the uploaded file.
|
|
871
|
+
|
|
872
|
+
- The `derivation.upload` instrumentation event payload now includes only
|
|
873
|
+
`:derivation` key.
|
|
874
|
+
|
|
875
|
+
* `download_endpoint`
|
|
876
|
+
|
|
877
|
+
- Support for legacy `/:storage/:id` URLs has been dropped.
|
|
878
|
+
|
|
879
|
+
- The `:storages` plugin option has been removed.
|
|
880
|
+
|
|
881
|
+
- The `Shrine::Plugins::DownloadEndpoint::App` constant has been removed.
|
|
882
|
+
|
|
883
|
+
* `data_uri`
|
|
884
|
+
|
|
885
|
+
- The deprecated `:filename` plugin option has been removed.
|
|
886
|
+
|
|
887
|
+
- The deprecated `Shrine::Plugins::DataUri::DataFile` constant has been
|
|
888
|
+
removed.
|
|
889
|
+
|
|
890
|
+
* `rack_file`
|
|
891
|
+
|
|
892
|
+
- The deprecated `Shrine::Plugins::RackFile::UploadedFile` constant has been
|
|
893
|
+
removed.
|
|
894
|
+
|
|
895
|
+
- Passing a Rack uploaded file hash to `Shrine#upload` is not supported
|
|
896
|
+
anymore.
|
|
897
|
+
|
|
898
|
+
* `cached_attachment_data`
|
|
899
|
+
|
|
900
|
+
- The `#<name>_cached_data=` model method has been removed.
|
|
901
|
+
|
|
902
|
+
- The `Attacher#read_cached` method has been renamed to
|
|
903
|
+
`Attacher#cached_data`.
|
|
904
|
+
|
|
905
|
+
* `default_url`
|
|
906
|
+
|
|
907
|
+
- Passing a block when loading the plugin is not supported anymore.
|
|
908
|
+
|
|
909
|
+
* `determine_mime_type`
|
|
910
|
+
|
|
911
|
+
- The deprecated `:default` analyzer alias has been removed.
|
|
912
|
+
|
|
913
|
+
- The private `Shrine#mime_type_analyzers` method has been removed.
|
|
914
|
+
|
|
915
|
+
* `store_dimensions`
|
|
916
|
+
|
|
917
|
+
- Failing to extract dimensions now prints out a warning by default.
|
|
918
|
+
|
|
919
|
+
- The private `Shrine#extract_dimensions` and `Shrine#dimensions_analyzers`
|
|
920
|
+
methods have been removed.
|
|
921
|
+
|
|
922
|
+
* `infer_extension`
|
|
923
|
+
|
|
924
|
+
- The `:mini_mime` inferrer is now the default inferrer, which requires the
|
|
925
|
+
`mini_mime` gem.
|
|
926
|
+
|
|
927
|
+
- The private `Shrine#infer_extension` method has been removed.
|
|
928
|
+
|
|
929
|
+
* `validation_helpers`
|
|
930
|
+
|
|
931
|
+
- The width & height validators will now raise an exception if `width` or
|
|
932
|
+
`height` metadata is missing.
|
|
933
|
+
|
|
934
|
+
- Support for regexes has been dropped for MIME type and extension
|
|
935
|
+
validators.
|
|
936
|
+
|
|
937
|
+
* `versions`
|
|
938
|
+
|
|
939
|
+
- The deprecated `:version_names`, `Shrine.version_names` and
|
|
940
|
+
`Shrine.version?` have been removed from `versions` plugin.
|
|
941
|
+
|
|
942
|
+
* `keep_files`
|
|
943
|
+
|
|
944
|
+
- The plugin will now always prevent deletion of both replaced and destroyed
|
|
945
|
+
attachments. The `:replaced` and `:destroyed` options don't have effect
|
|
946
|
+
anymore.
|
|
947
|
+
|
|
948
|
+
* `dynamic_storage`
|
|
949
|
+
|
|
950
|
+
- The `Shrine.dynamic_storages` method has been removed.
|
|
951
|
+
|
|
952
|
+
* `instrumentation`
|
|
953
|
+
|
|
954
|
+
- The `:location`, `:upload_options`, and `:metadata` keys have been removed
|
|
955
|
+
from `:options` in `upload.shrine` event payload.
|
|
956
|
+
|
|
957
|
+
- The `:metadata` key has been removed from `metadata.shrine` event payload.
|
|
958
|
+
|
|
959
|
+
* `default_storage`
|
|
960
|
+
|
|
961
|
+
- Passing `record` & `name` arguments to the storage block has been
|
|
962
|
+
deprecated over evaluating the block in context of the attacher instance.
|
|
963
|
+
|
|
964
|
+
* `sequel`
|
|
965
|
+
|
|
966
|
+
- The `:callbacks` plugin option has been renamed to `:hooks`.
|
|
967
|
+
|
|
968
|
+
[derivatives]: https://shrinerb.com/docs/plugins/derivatives
|
|
969
|
+
[versions]: https://shrinerb.com/docs/plugins/versions
|
|
970
|
+
[backgrounding]: https://shrinerb.com/docs/plugins/backgrounding
|
|
971
|
+
[shrine-memory]: https://github.com/shrinerb/shrine-memory
|
|
972
|
+
[atomic_helpers]: https://shrinerb.com/docs/plugins/atomic_helpers
|
|
973
|
+
[attacher]: https://shrinerb.com/docs/attacher
|
|
974
|
+
[column]: https://shrinerb.com/docs/plugins/column
|
|
975
|
+
[entity]: https://shrinerb.com/docs/plugins/entity
|
|
976
|
+
[model]: https://shrinerb.com/docs/plugins/model
|
|
977
|
+
[persistence]: https://shrinerb.com/docs/plugins/persistence
|
|
978
|
+
[mirroring]: https://shrinerb.com/docs/plugins/mirroring
|
|
979
|
+
[form_assign]: https://shrinerb.com/docs/plugins/form_assign
|
|
980
|
+
[multi_cache]: https://shrinerb.com/docs/plugins/multi_cache
|
|
981
|
+
[Upgrading to Shrine 3.x]: https://shrinerb.com/docs/upgrading-to-3
|