shrine 3.0.1 → 3.3.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.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +82 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +15 -5
  5. data/doc/advantages.md +33 -16
  6. data/doc/attacher.md +2 -2
  7. data/doc/carrierwave.md +78 -34
  8. data/doc/changing_derivatives.md +39 -39
  9. data/doc/design.md +134 -85
  10. data/doc/direct_s3.md +1 -0
  11. data/doc/external/articles.md +57 -45
  12. data/doc/external/extensions.md +41 -35
  13. data/doc/external/misc.md +23 -8
  14. data/doc/getting_started.md +177 -112
  15. data/doc/metadata.md +79 -43
  16. data/doc/multiple_files.md +6 -4
  17. data/doc/paperclip.md +119 -42
  18. data/doc/plugins/activerecord.md +1 -1
  19. data/doc/plugins/add_metadata.md +112 -35
  20. data/doc/plugins/atomic_helpers.md +41 -3
  21. data/doc/plugins/backgrounding.md +12 -2
  22. data/doc/plugins/column.md +36 -7
  23. data/doc/plugins/data_uri.md +2 -2
  24. data/doc/plugins/default_url.md +6 -3
  25. data/doc/plugins/derivation_endpoint.md +26 -28
  26. data/doc/plugins/derivatives.md +238 -171
  27. data/doc/plugins/determine_mime_type.md +2 -2
  28. data/doc/plugins/download_endpoint.md +5 -5
  29. data/doc/plugins/dynamic_storage.md +1 -1
  30. data/doc/plugins/form_assign.md +5 -5
  31. data/doc/plugins/included.md +25 -5
  32. data/doc/plugins/infer_extension.md +11 -2
  33. data/doc/plugins/instrumentation.md +1 -1
  34. data/doc/plugins/metadata_attributes.md +22 -10
  35. data/doc/plugins/mirroring.md +1 -1
  36. data/doc/plugins/persistence.md +11 -1
  37. data/doc/plugins/refresh_metadata.md +5 -4
  38. data/doc/plugins/remote_url.md +8 -3
  39. data/doc/plugins/remove_invalid.md +9 -1
  40. data/doc/plugins/signature.md +11 -2
  41. data/doc/plugins/store_dimensions.md +12 -2
  42. data/doc/plugins/type_predicates.md +96 -0
  43. data/doc/plugins/upload_endpoint.md +7 -11
  44. data/doc/plugins/upload_options.md +1 -1
  45. data/doc/plugins/url_options.md +4 -4
  46. data/doc/plugins/validation.md +14 -4
  47. data/doc/plugins/validation_helpers.md +3 -3
  48. data/doc/plugins/versions.md +7 -7
  49. data/doc/processing.md +290 -127
  50. data/doc/refile.md +39 -18
  51. data/doc/release_notes/2.19.0.md +1 -1
  52. data/doc/release_notes/2.8.0.md +1 -1
  53. data/doc/release_notes/3.0.0.md +1 -1
  54. data/doc/release_notes/3.0.1.md +4 -0
  55. data/doc/release_notes/3.1.0.md +73 -0
  56. data/doc/release_notes/3.2.0.md +96 -0
  57. data/doc/release_notes/3.2.1.md +31 -0
  58. data/doc/release_notes/3.2.2.md +14 -0
  59. data/doc/release_notes/3.3.0.md +105 -0
  60. data/doc/securing_uploads.md +3 -3
  61. data/doc/storage/file_system.md +1 -1
  62. data/doc/storage/memory.md +19 -0
  63. data/doc/storage/s3.md +105 -82
  64. data/doc/testing.md +2 -2
  65. data/doc/upgrading_to_3.md +97 -49
  66. data/doc/validation.md +3 -2
  67. data/lib/shrine.rb +8 -8
  68. data/lib/shrine/attacher.rb +24 -14
  69. data/lib/shrine/attachment.rb +5 -5
  70. data/lib/shrine/plugins.rb +22 -0
  71. data/lib/shrine/plugins/activerecord.rb +1 -1
  72. data/lib/shrine/plugins/add_metadata.rb +18 -7
  73. data/lib/shrine/plugins/backgrounding.rb +2 -2
  74. data/lib/shrine/plugins/default_storage.rb +6 -6
  75. data/lib/shrine/plugins/default_url.rb +1 -1
  76. data/lib/shrine/plugins/derivation_endpoint.rb +12 -7
  77. data/lib/shrine/plugins/derivatives.rb +61 -29
  78. data/lib/shrine/plugins/determine_mime_type.rb +3 -3
  79. data/lib/shrine/plugins/entity.rb +6 -6
  80. data/lib/shrine/plugins/mirroring.rb +8 -8
  81. data/lib/shrine/plugins/model.rb +3 -3
  82. data/lib/shrine/plugins/presign_endpoint.rb +16 -4
  83. data/lib/shrine/plugins/pretty_location.rb +1 -1
  84. data/lib/shrine/plugins/processing.rb +1 -1
  85. data/lib/shrine/plugins/refresh_metadata.rb +2 -2
  86. data/lib/shrine/plugins/remote_url.rb +3 -3
  87. data/lib/shrine/plugins/remove_attachment.rb +5 -0
  88. data/lib/shrine/plugins/remove_invalid.rb +10 -5
  89. data/lib/shrine/plugins/sequel.rb +1 -1
  90. data/lib/shrine/plugins/signature.rb +7 -6
  91. data/lib/shrine/plugins/store_dimensions.rb +22 -11
  92. data/lib/shrine/plugins/type_predicates.rb +113 -0
  93. data/lib/shrine/plugins/upload_endpoint.rb +10 -5
  94. data/lib/shrine/plugins/upload_options.rb +2 -2
  95. data/lib/shrine/plugins/url_options.rb +2 -2
  96. data/lib/shrine/plugins/validation.rb +9 -7
  97. data/lib/shrine/storage/linter.rb +4 -4
  98. data/lib/shrine/storage/memory.rb +5 -3
  99. data/lib/shrine/storage/s3.rb +117 -38
  100. data/lib/shrine/uploaded_file.rb +0 -1
  101. data/lib/shrine/version.rb +2 -2
  102. data/shrine.gemspec +7 -8
  103. metadata +25 -31
@@ -2,7 +2,7 @@
2
2
  title: Derivatives
3
3
  ---
4
4
 
5
- The derivatives plugin allows storing processed files ("derivatives") alongside
5
+ The [`derivatives`][derivatives] plugin allows storing processed files ("derivatives") alongside
6
6
  the main attached file. The processed file data will be saved together with the
7
7
  main attachment data in the same record attribute.
8
8
 
@@ -10,12 +10,11 @@ main attachment data in the same record attribute.
10
10
  Shrine.plugin :derivatives
11
11
  ```
12
12
 
13
- ## Creating derivatives
13
+ ## Quick start
14
14
 
15
- When you have a file attached, you can generate derivatives from it and save
16
- them alongside the attached file. The simplest way to do this is to define a
17
- processor which returns the processed files, and then trigger it when you want
18
- to create derivatives.
15
+ You'll usually want to create derivatives from an attached file. The simplest
16
+ way to do this is to define a processor which returns the processed files, and
17
+ then trigger it when you want to create derivatives.
19
18
 
20
19
  Here is an example of generating image thumbnails:
21
20
 
@@ -27,7 +26,7 @@ gem "image_processing", "~> 1.8"
27
26
  require "image_processing/mini_magick"
28
27
 
29
28
  class ImageUploader < Shrine
30
- Attacher.derivatives_processor do |original|
29
+ Attacher.derivatives do |original|
31
30
  magick = ImageProcessing::MiniMagick.source(original)
32
31
 
33
32
  {
@@ -39,56 +38,149 @@ class ImageUploader < Shrine
39
38
  end
40
39
  ```
41
40
  ```rb
42
- class Photo < Model(:image_data)
43
- include ImageUploader::Attachment(:image)
44
- end
45
- ```
46
- ```rb
47
41
  photo = Photo.new(image: file)
48
- photo.image_derivatives! # calls derivatives processor and uploads results
42
+ photo.image_derivatives! # creates derivatives
49
43
  photo.save
50
44
  ```
51
45
 
52
- If you're allowing the attached file to be updated later on, in your update
53
- route make sure to create derivatives for new attachments:
46
+ You can then retrieve the URL of a processed derivative:
54
47
 
55
48
  ```rb
56
- photo.image_derivatives! if photo.image_changed?
49
+ photo.image_url(:large) #=> "https://s3.amazonaws.com/path/to/large.jpg"
57
50
  ```
58
51
 
59
- Once derivatives have been created, their data is stored in the `#<name>_data`
60
- record attribute alongside the main file data:
52
+ The derivatives data is stored in the `<attachment>_data` column alongside the
53
+ main file:
61
54
 
62
55
  ```rb
63
56
  photo.image_data #=>
64
57
  # {
65
- # "id": "original.jpg",
58
+ # "id": "path/to/original.jpg",
66
59
  # "store": "store",
67
60
  # "metadata": { ... },
68
61
  # "derivatives": {
69
- # "small": { "id": "small.jpg", "storage": "store", "metadata": { ... } },
70
- # "medium": { "id": "medium.jpg", "storage": "store", "metadata": { ... } },
71
- # "large": { "id": "large.jpg", "storage": "store", "metadata": { ... } },
62
+ # "small": { "id": "path/to/small.jpg", "storage": "store", "metadata": { ... } },
63
+ # "medium": { "id": "path/to/medium.jpg", "storage": "store", "metadata": { ... } },
64
+ # "large": { "id": "path/to/large.jpg", "storage": "store", "metadata": { ... } },
72
65
  # }
73
66
  # }
74
67
  ```
75
68
 
76
- You can then retrieve derivatives as follows:
69
+ And they can be retrieved as `Shrine::UploadedFile` objects:
77
70
 
78
71
  ```rb
79
- photo.image(:large) #=> #<Shrine::UploadedFile>
72
+ photo.image(:large) #=> #<Shrine::UploadedFile id="path/to/large.jpg" storage=:store metadata={...}>
80
73
  photo.image(:large).url #=> "https://s3.amazonaws.com/path/to/large.jpg"
81
- photo.image(:large).size #=> 43843
74
+ photo.image(:large).size #=> 5825949
82
75
  photo.image(:large).mime_type #=> "image/jpeg"
83
76
  ```
84
77
 
85
- The `#<name>_derivatives!` model method delegates to
86
- `Attacher#create_derivatives`, which you can use if you're using
87
- `Shrine::Attacher` directly:
78
+ ## Retrieving derivatives
79
+
80
+ The list of stored derivatives can be retrieved with `#<name>_derivatives`:
81
+
82
+ ```rb
83
+ photo.image_derivatives #=>
84
+ # {
85
+ # small: #<Shrine::UploadedFile ...>,
86
+ # medium: #<Shrine::UploadedFile ...>,
87
+ # large: #<Shrine::UploadedFile ...>,
88
+ # }
89
+ ```
90
+
91
+ A specific derivative can be retrieved in any of the following ways:
92
+
93
+ ```rb
94
+ photo.image_derivatives[:small] #=> #<Shrine::UploadedFile ...>
95
+ photo.image_derivatives(:small) #=> #<Shrine::UploadedFile ...>
96
+ photo.image(:small) #=> #<Shrine::UploadedFile ...>
97
+ ```
98
+
99
+ Or with nested derivatives:
100
+
101
+ ```rb
102
+ photo.image_derivatives #=> { thumbnail: { small: ..., medium: ..., large: ... } }
103
+
104
+ photo.image_derivatives.dig(:thumbnail, :small) #=> #<Shrine::UploadedFile ...>
105
+ photo.image_derivatives(:thumbnail, :small) #=> #<Shrine::UploadedFile ...>
106
+ photo.image(:thumbnails, :small) #=> #<Shrine::UploadedFile ...>
107
+ ```
108
+
109
+ ### Derivative URL
110
+
111
+ You can retrieve the URL of a derivative URL with `#<name>_url`:
112
+
113
+ ```rb
114
+ photo.image_url(:small) #=> "https://example.com/small.jpg"
115
+ photo.image_url(:medium) #=> "https://example.com/medium.jpg"
116
+ photo.image_url(:large) #=> "https://example.com/large.jpg"
117
+ ```
118
+
119
+ For nested derivatives you can pass multiple keys:
120
+
121
+ ```rb
122
+ photo.image_derivatives #=> { thumbnail: { small: ..., medium: ..., large: ... } }
123
+
124
+ photo.image_url(:thumbnail, :medium) #=> "https://example.com/medium.jpg"
125
+ ```
126
+
127
+ By default, `#<name>_url` method will return `nil` if derivative is not found.
128
+ You can use the [`default_url`][default_url] plugin to set up URL fallbacks:
129
+
130
+ ```rb
131
+ Attacher.default_url do |derivative: nil, **|
132
+ "/fallbacks/#{derivative}.jpg" if derivative
133
+ end
134
+ ```
135
+ ```rb
136
+ photo.image_url(:medium) #=> "https://example.com/fallbacks.com/medium.jpg"
137
+ ```
138
+
139
+ Any additional URL options passed to `#<name>_url` will be forwarded to the
140
+ storage:
141
+
142
+ ```rb
143
+ photo.image_url(:small, response_content_disposition: "attachment")
144
+ ```
145
+
146
+ You can also retrieve the derivative URL via `UploadedFile#url`:
147
+
148
+ ```rb
149
+ photo.image_derivatives[:large].url
150
+ ```
151
+
152
+ ## Attacher API
153
+
154
+ The derivatives API is primarily defined on the `Shrine::Attacher` class, with
155
+ some important methods also being exposed through the `Shrine::Attachment`
156
+ module.
157
+
158
+ Here is a model example with equivalent attacher code:
159
+
160
+ ```rb
161
+ photo.image_derivatives!(:thumbnails)
162
+ photo.image_derivatives #=> { ... }
163
+
164
+ photo.image_url(:large) #=> "https://..."
165
+ photo.image(:large) #=> #<Shrine::UploadedFile ...>
166
+ ```
167
+ ```rb
168
+ attacher.create_derivatives(:thumbnails)
169
+ attacher.get_derivatives #=> { ... }
170
+
171
+ attacher.url(:large) #=> "https://..."
172
+ attacher.get(:large) #=> "#<Shrine::UploadedFile>"
173
+ ```
174
+
175
+ ## Creating derivatives
176
+
177
+ By default, the `Attacher#create_derivatives` method downloads the attached
178
+ file, calls the processor, uploads results to attacher's permanent storage, and
179
+ saves uploaded files on the attacher.
88
180
 
89
181
  ```rb
90
182
  attacher.file #=> #<Shrine::UploadedFile id="original.jpg" storage=:store ...>
91
- attacher.create_derivatives # calls registered processor and uploads results
183
+ attacher.create_derivatives # calls default processor and uploads results
92
184
  attacher.derivatives #=>
93
185
  # {
94
186
  # small: #<Shrine::UploadedFile id="small.jpg" storage=:store ...>,
@@ -97,9 +189,7 @@ attacher.derivatives #=>
97
189
  # }
98
190
  ```
99
191
 
100
- By default, the `Attacher#create_derivatives` method downloads the attached
101
- file, calls the processor, uploads results to attacher's permanent storage, and
102
- saves uploaded files on the attacher. Any additional arguments are forwarded to
192
+ Any additional arguments are forwarded to
103
193
  [`Attacher#process_derivatives`](#processing-derivatives):
104
194
 
105
195
  ```rb
@@ -107,35 +197,59 @@ attacher.create_derivatives(different_source) # pass a different source file
107
197
  attacher.create_derivatives(foo: "bar") # pass custom options to the processor
108
198
  ```
109
199
 
200
+ ### Create on promote
201
+
202
+ You can also have derivatives created automatically on promotion:
203
+
204
+ ```rb
205
+ Shrine.plugin :derivatives, create_on_promote: true
206
+ ```
207
+ ```rb
208
+ attacher.assign(file)
209
+ attacher.finalize # creates derivatives on promotion
210
+ attacher.derivatives #=> { small: ..., medium: ..., large: ... }
211
+ ```
212
+
110
213
  ### Naming processors
111
214
 
112
215
  If you want to have multiple processors for an uploader, you can assign each
113
- processor a name. Then when creating derivatives you can specify the name of
114
- the desired processor.
216
+ processor a name:
115
217
 
116
218
  ```rb
117
219
  class ImageUploader < Shrine
118
- Attacher.derivatives_processor :thumbnails do |original|
119
- # ...
220
+ Attacher.derivatives :thumbnails do |original|
221
+ { large: ..., medium: ..., small: ... }
120
222
  end
121
223
 
122
- Attacher.derivatives_processor :crop do |original|
123
- # ...
224
+ Attacher.derivatives :crop do |original|
225
+ { cropped: ... }
124
226
  end
125
-
126
- # ...
127
227
  end
128
228
  ```
229
+
230
+ Then when creating derivatives you can specify the name of the desired
231
+ processor. New derivatives will be merged with any existing ones.
232
+
129
233
  ```rb
130
- photo.image_derivatives!(:thumbnails)
131
- # or
132
234
  attacher.create_derivatives(:thumbnails)
235
+ attacher.derivatives #=> { large: ..., medium: ..., small: ... }
236
+
237
+ attacher.create_derivatives(:crop)
238
+ attacher.derivatives #=> { large: ..., medium: ..., small: ..., cropped: ... }
133
239
  ```
134
240
 
135
241
  ### Derivatives storage
136
242
 
137
243
  By default, derivatives are uploaded to the permanent storage of the attacher.
138
- You can change the default destination storage with the `:storage` plugin
244
+ You can change the destination storage by passing `:storage` to the creation
245
+ call:
246
+
247
+ ```rb
248
+ attacher.create_derivatives(storage: :cache) # will be promoted together with main file
249
+ attacher.create_derivatives(storage: :other_store)
250
+ ```
251
+
252
+ You can also change the default destination storage with the `:storage` plugin
139
253
  option:
140
254
 
141
255
  ```rb
@@ -172,11 +286,14 @@ The storage block is evaluated in the context of a `Shrine::Attacher` instance:
172
286
 
173
287
  ```rb
174
288
  Attacher.derivatives_storage do |derivative|
175
- self #=> #<Shrine::Attacher>
289
+ self #=> #<Shrine::Attacher>
176
290
 
291
+ file #=> #<Shrine::UploadedFile>
177
292
  record #=> #<Photo>
178
293
  name #=> :image
179
294
  context #=> { ... }
295
+
296
+ # ...
180
297
  end
181
298
  ```
182
299
 
@@ -186,7 +303,7 @@ Derivatives can be nested to any level, using both hashes and arrays, but the
186
303
  top-level object must be a hash.
187
304
 
188
305
  ```rb
189
- Attacher.derivatives_processor :tiff do |original|
306
+ Attacher.derivatives :tiff do |original|
190
307
  {
191
308
  thumbnail: {
192
309
  small: small,
@@ -201,114 +318,29 @@ Attacher.derivatives_processor :tiff do |original|
201
318
  }
202
319
  end
203
320
  ```
204
-
205
- ## Retrieving derivatives
206
-
207
- If you're using the `Shrine::Attachment` module, you can retrieve stored
208
- derivatives by calling `#<name>_derivatives` on your model/entity.
209
-
210
- ```rb
211
- class Photo < Model(:image_data)
212
- include ImageUploader::Attachment(:image)
213
- end
214
- ```
215
- ```rb
216
- photo.image_derivatives #=>
217
- # {
218
- # small: #<Shrine::UploadedFile>,
219
- # medium: #<Shrine::UploadedFile>,
220
- # large: #<Shrine::UploadedFile>,
221
- # }
222
- ```
223
-
224
- A specific derivative can be retrieved in any of the following ways:
225
-
226
- ```rb
227
- photo.image_derivatives[:small] #=> #<Shrine::UploadedFile>
228
- photo.image_derivatives(:small) #=> #<Shrine::UploadedFile>
229
- photo.image(:small) #=> #<Shrine::UploadedFile>
230
- ```
231
-
232
- And with nested derivatives:
233
-
234
- ```rb
235
- photo.image_derivatives #=> { thumbnail: { small: ..., medium: ..., large: ... } }
236
-
237
- photo.image_derivatives.dig(:thumbnail, :small) #=> #<Shrine::UploadedFile>
238
- photo.image_derivatives(:thumbnail, :small) #=> #<Shrine::UploadedFile>
239
- photo.image(:thumbnails, :small) #=> #<Shrine::UploadedFile>
240
- ```
241
-
242
- When using `Shrine::Attacher` directly, you can retrieve derivatives using
243
- `Attacher#derivatives`:
244
-
245
321
  ```rb
246
322
  attacher.derivatives #=>
247
323
  # {
248
- # small: #<Shrine::UploadedFile>,
249
- # medium: #<Shrine::UploadedFile>,
250
- # large: #<Shrine::UploadedFile>,
324
+ # thumbnail: {
325
+ # small: #<Shrine::UploadedFile ...>,
326
+ # medium: #<Shrine::UploadedFile ...>,
327
+ # large: #<Shrine::UploadedFile ...>,
328
+ # },
329
+ # layers: [
330
+ # #<Shrine::UploadedFile ...>,
331
+ # #<Shrine::UploadedFile ...>,
332
+ # # ...
333
+ # ]
251
334
  # }
252
335
  ```
253
336
 
254
- ## Derivative URL
255
-
256
- If you're using the `Shrine::Attachment` module, you can use the `#<name>_url`
257
- method to retrieve the URL of a derivative.
258
-
259
- ```rb
260
- class Photo < Model(:image_data)
261
- include ImageUploader::Attachment(:image)
262
- end
263
- ```
264
- ```rb
265
- photo.image_url(:small) #=> "https://example.com/small.jpg"
266
- photo.image_url(:medium) #=> "https://example.com/medium.jpg"
267
- photo.image_url(:large) #=> "https://example.com/large.jpg"
268
- ```
269
-
270
- For nested derivatives you can pass multiple keys:
271
-
272
- ```rb
273
- photo.image_derivatives #=> { thumbnail: { small: ..., medium: ..., large: ... } }
274
-
275
- photo.image_url(:thumbnail, :medium) #=> "https://example.com/medium.jpg"
276
- ```
277
-
278
- By default, `#<name>_url` method will return `nil` if derivative is not found.
279
- You can use the [`default_url`][default_url] plugin to set up URL fallbacks:
280
-
281
- ```rb
282
- Attacher.default_url do |derivative: nil, **|
283
- "https://my-app.com/fallbacks/#{derivative}.jpg" if derivative
284
- end
285
- ```
286
- ```rb
287
- photo.image_url(:medium) #=> "https://example.com/fallbacks.com/medium.jpg"
288
- ```
289
-
290
- Any additional URL options passed to `#<name>_url` will be forwarded to the
291
- storage:
292
-
293
- ```rb
294
- photo.image_url(:small, response_content_disposition: "attachment")
295
- ```
296
-
297
- You can also retrieve the derivative URL via `UploadedFile#url`:
298
-
299
- ```rb
300
- photo.image_derivatives[:large].url
301
- # or
302
- attacher.derivatives[:large].url
303
- ```
304
-
305
337
  ## Processing derivatives
306
338
 
307
339
  A derivatives processor block takes the original file, and is expected to
308
340
  return a hash of processed files (it can be [nested](#nesting-derivatives)).
309
341
 
310
342
  ```rb
311
- Attacher.derivatives_processor :my_processor do |original|
343
+ Attacher.derivatives :my_processor do |original|
312
344
  # return a hash of processed files
313
345
  end
314
346
  ```
@@ -327,9 +359,10 @@ The processor block is evaluated in context of the `Shrine::Attacher` instance,
327
359
  which allows you to change your processing logic based on the record data.
328
360
 
329
361
  ```rb
330
- Attacher.derivatives_processor :my_processor do |original|
362
+ Attacher.derivatives :my_processor do |original|
331
363
  self #=> #<Shrine::Attacher>
332
364
 
365
+ file #=> #<Shrine::UploadedFile>
333
366
  record #=> #<Photo>
334
367
  name #=> :image
335
368
  context #=> { ... }
@@ -345,7 +378,7 @@ forwarded to the processor:
345
378
  attacher.process_derivatives(:my_processor, foo: "bar")
346
379
  ```
347
380
  ```rb
348
- Attacher.derivatives_processor :my_processor do |original, **options|
381
+ Attacher.derivatives :my_processor do |original, **options|
349
382
  options #=> { :foo => "bar" }
350
383
  # ...
351
384
  end
@@ -357,7 +390,7 @@ By default, the `Attacher#process_derivatives` method will download the
357
390
  attached file and pass it to the processor:
358
391
 
359
392
  ```rb
360
- Attacher.derivatives_processor :my_processor do |original|
393
+ Attacher.derivatives :my_processor do |original|
361
394
  original #=> #<File:...>
362
395
  # ...
363
396
  end
@@ -366,29 +399,54 @@ end
366
399
  attacher.process_derivatives(:my_processor) # downloads attached file and passes it to the processor
367
400
  ```
368
401
 
369
- If you want to use a different source file, or if you're calling multiple
370
- processors in a row and want to avoid re-downloading the same source file each
371
- time, you can pass the source file as the second argument:
402
+ If you want to use a different source file, you can pass it in to the process
403
+ call. Typically you'd pass a local file on disk. If you pass a
404
+ `Shrine::UploadedFile` object or another IO-like object, it will be
405
+ automatically downloaded/copied to a local TempFile on disk.
406
+
407
+ ```rb
408
+ # named processor:
409
+ attacher.process_derivatives(:my_processor, source_file)
410
+
411
+ # default processor:
412
+ attacher.process_derivatives(source_file)
413
+ ```
414
+
415
+ If you want to call multiple processors in a row with the same source file, you
416
+ can use this to avoid re-downloading the same source file each time:
372
417
 
373
418
  ```rb
374
- # this way the source file is downloaded only once
375
419
  attacher.file.download do |original|
376
420
  attacher.process_derivatives(:thumbnails, original)
377
421
  attacher.process_derivatives(:colors, original)
378
422
  end
379
423
  ```
380
424
 
425
+ If a processor might not always need a local source file, you avoid a
426
+ potentially expensive download/copy by registering the processor with
427
+ `download: false`, in which case the source file will be passed to the
428
+ processor as is.
429
+
430
+ ```rb
431
+ Attacher.derivatives :my_processor, download: false do |source|
432
+ source #=> Could be File, Shrine::UploadedFile, or other IO-like object
433
+ shrine_class.with_file(source) do |file|
434
+ # can force download/copy if necessary with `with_file`,
435
+ end
436
+ end
437
+ ```
438
+
381
439
  ## Adding derivatives
382
440
 
383
441
  If you already have processed files that you want to save, you can do that with
384
442
  `Attacher#add_derivatives`:
385
443
 
386
444
  ```rb
387
- attacher.add_derivatives(
445
+ attacher.add_derivatives({
388
446
  one: file_1,
389
447
  two: file_2,
390
448
  # ...
391
- )
449
+ })
392
450
 
393
451
  attacher.derivatives #=>
394
452
  # {
@@ -402,7 +460,7 @@ New derivatives will be merged with existing ones:
402
460
 
403
461
  ```rb
404
462
  attacher.derivatives #=> { one: #<Shrine::UploadedFile> }
405
- attacher.add_derivatives(two: two_file)
463
+ attacher.add_derivatives({ two: two_file })
406
464
  attacher.derivatives #=> { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> }
407
465
  ```
408
466
 
@@ -410,7 +468,7 @@ The merging is deep, so the following will work as well:
410
468
 
411
469
  ```rb
412
470
  attacher.derivatives #=> { nested: { one: #<Shrine::UploadedFile> } }
413
- attacher.add_derivatives(nested: { two: two_file })
471
+ attacher.add_derivatives({ nested: { two: two_file } })
414
472
  attacher.derivatives #=> { nested: { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> } }
415
473
  ```
416
474
 
@@ -421,6 +479,11 @@ For adding a single derivative, you can also use the singular
421
479
  attacher.add_derivative(:thumb, thumbnail_file)
422
480
  ```
423
481
 
482
+ > Note that new derivatives will replace any existing derivatives living under
483
+ the same key, but won't delete them. If this is your case, make sure to save a
484
+ reference to the old derivatives before assigning new ones, and then delete
485
+ them after persisting the change.
486
+
424
487
  Any options passed to `Attacher#add_derivative(s)` will be forwarded to
425
488
  [`Attacher#upload_derivatives`](#uploading-derivatives).
426
489
 
@@ -437,11 +500,11 @@ If you want to upload processed files without setting them, you can use
437
500
  `Attacher#upload_derivatives`:
438
501
 
439
502
  ```rb
440
- derivatives = attacher.upload_derivatives(
503
+ derivatives = attacher.upload_derivatives({
441
504
  one: file_1,
442
505
  two: file_2,
443
506
  # ...
444
- )
507
+ })
445
508
 
446
509
  derivatives #=>
447
510
  # {
@@ -479,9 +542,7 @@ attacher.upload_derivative :thumb, thumbnail_file,
479
542
  location: "path/to/derivative"
480
543
  ```
481
544
 
482
- A `:derivative` option is automatically passed to the uploader and holds the
483
- name of the derivative, which you can use when extracting metadata, generating
484
- location or generating upload options:
545
+ The `:derivative` name is automatically passed to the uploader:
485
546
 
486
547
  ```rb
487
548
  class MyUploader < Shrine
@@ -510,8 +571,6 @@ If you want to disable this behaviour, pass `delete: false`:
510
571
 
511
572
  ```rb
512
573
  attacher.upload_derivative(:thumb, thumbnail_file, delete: false)
513
-
514
- File.exist?(thumbnail_file.path) #=> true
515
574
  ```
516
575
 
517
576
  ## Merging derivatives
@@ -521,7 +580,7 @@ If you want to save already uploaded derivatives, you can use
521
580
 
522
581
  ```rb
523
582
  attacher.derivatives #=> { one: #<Shrine::UploadedFile> }
524
- attacher.merge_derivatives attacher.upload_derivatives(two: two_file)
583
+ attacher.merge_derivatives attacher.upload_derivatives({ two: two_file })
525
584
  attacher.derivatives #=> { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> }
526
585
  ```
527
586
 
@@ -529,10 +588,15 @@ This does a deep merge, so the following will work as well:
529
588
 
530
589
  ```rb
531
590
  attacher.derivatives #=> { nested: { one: #<Shrine::UploadedFile> } }
532
- attacher.merge_derivatives attacher.upload_derivatives(nested: { two: two_file })
591
+ attacher.merge_derivatives attacher.upload_derivatives({ nested: { two: two_file } })
533
592
  attacher.derivatives #=> { nested: { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> } }
534
593
  ```
535
594
 
595
+ > Note that new derivatives will replace any existing derivatives living under
596
+ the same key, but won't delete them. If this is your case, make sure to save a
597
+ reference to the old derivatives before assigning new ones, and then delete
598
+ them after persisting the change.
599
+
536
600
  The `Attacher#merge_derivatives` method is thread-safe.
537
601
 
538
602
  ### Setting derivatives
@@ -542,7 +606,7 @@ If instead of adding you want to *override* existing derivatives, you can use
542
606
 
543
607
  ```rb
544
608
  attacher.derivatives #=> { one: #<Shrine::UploadedFile> }
545
- attacher.set_derivatives attacher.upload_derivatives(two: two_file)
609
+ attacher.set_derivatives attacher.upload_derivatives({ two: two_file })
546
610
  attacher.derivatives #=> { two: #<Shrine::UploadedFile> }
547
611
  ```
548
612
 
@@ -650,7 +714,7 @@ You can store derivatives even if there is no main attached file:
650
714
 
651
715
  ```rb
652
716
  attacher.file #=> nil
653
- attacher.add_derivatives(one: one_file, two: two_file)
717
+ attacher.add_derivatives({ one: one_file, two: two_file })
654
718
  attacher.data #=>
655
719
  # {
656
720
  # "derivatives" => {
@@ -728,15 +792,17 @@ plugin :derivatives
728
792
  Processing derivatives will trigger a `derivatives.shrine` event with the
729
793
  following payload:
730
794
 
731
- | Key | Description |
732
- | :-- | :---- |
733
- | `:processor` | Name of the derivatives processor |
734
- | `:processor_options` | Any options passed to the processor |
735
- | `:uploader` | The uploader class that sent the event |
795
+ | Key | Description |
796
+ | :-- | :---- |
797
+ | `:processor` | Name of the derivatives processor |
798
+ | `:processor_options` | Any options passed to the processor |
799
+ | `:io` | The source file passed to the processor |
800
+ | `:attacher` | The attacher instance doing the processing |
801
+ | `:uploader` | The uploader class that sent the event |
736
802
 
737
803
  A default log subscriber is added as well which logs these events:
738
804
 
739
- ```plaintext
805
+ ```
740
806
  Derivatives (2133ms) – {:processor=>:thumbnails, :processor_options=>{}, :uploader=>ImageUploader}
741
807
  ```
742
808
 
@@ -747,8 +813,8 @@ plugin :derivatives, log_subscriber: -> (event) {
747
813
  Shrine.logger.info JSON.generate(name: event.name, duration: event.duration, **event.payload)
748
814
  }
749
815
  ```
750
- ```plaintext
751
- {"name":"derivatives","duration":2133,"processor":"thumbnails","processor_options":{},"uploader":"ImageUploader"}
816
+ ```
817
+ {"name":"derivatives","duration":2133,"processor":"thumbnails","processor_options":{},"io":"#<File:...>","uploader":"ImageUploader"}
752
818
  ```
753
819
 
754
820
  Or disable logging altogether:
@@ -757,6 +823,7 @@ Or disable logging altogether:
757
823
  plugin :derivatives, log_subscriber: nil
758
824
  ```
759
825
 
826
+ [derivatives]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/derivatives.rb
760
827
  [default_url]: https://shrinerb.com/docs/plugins/default_url
761
828
  [entity]: https://shrinerb.com/docs/plugins/entity
762
829
  [model]: https://shrinerb.com/docs/plugins/model