shrine 3.1.0 → 3.4.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 +82 -0
- data/README.md +11 -4
- data/doc/advantages.md +4 -4
- data/doc/attacher.md +2 -2
- data/doc/carrierwave.md +24 -12
- data/doc/changing_derivatives.md +1 -1
- data/doc/changing_location.md +6 -5
- data/doc/design.md +134 -85
- data/doc/direct_s3.md +26 -0
- data/doc/external/articles.md +57 -45
- data/doc/external/extensions.md +41 -35
- data/doc/external/misc.md +23 -8
- data/doc/getting_started.md +156 -85
- data/doc/metadata.md +80 -44
- data/doc/multiple_files.md +1 -1
- data/doc/paperclip.md +28 -9
- data/doc/plugins/add_metadata.md +112 -35
- data/doc/plugins/atomic_helpers.md +41 -3
- data/doc/plugins/backgrounding.md +12 -2
- data/doc/plugins/column.md +36 -7
- data/doc/plugins/default_url.md +6 -3
- data/doc/plugins/derivatives.md +83 -44
- data/doc/plugins/download_endpoint.md +5 -5
- data/doc/plugins/dynamic_storage.md +1 -1
- data/doc/plugins/entity.md +12 -4
- data/doc/plugins/form_assign.md +5 -5
- data/doc/plugins/included.md +25 -5
- data/doc/plugins/infer_extension.md +9 -0
- data/doc/plugins/instrumentation.md +1 -1
- data/doc/plugins/metadata_attributes.md +1 -0
- data/doc/plugins/mirroring.md +1 -1
- data/doc/plugins/model.md +8 -3
- data/doc/plugins/persistence.md +10 -1
- data/doc/plugins/remote_url.md +6 -1
- data/doc/plugins/remove_invalid.md +9 -1
- data/doc/plugins/sequel.md +1 -1
- data/doc/plugins/store_dimensions.md +10 -0
- data/doc/plugins/type_predicates.md +96 -0
- data/doc/plugins/upload_endpoint.md +1 -1
- data/doc/plugins/upload_options.md +1 -1
- data/doc/plugins/url_options.md +4 -4
- data/doc/plugins/validation.md +14 -4
- data/doc/plugins/versions.md +7 -7
- data/doc/processing.md +287 -123
- data/doc/refile.md +9 -9
- data/doc/release_notes/2.8.0.md +1 -1
- data/doc/release_notes/3.0.0.md +1 -1
- 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/securing_uploads.md +2 -2
- data/doc/storage/memory.md +19 -0
- data/doc/storage/s3.md +104 -77
- data/doc/testing.md +12 -2
- data/doc/upgrading_to_3.md +99 -53
- data/lib/shrine.rb +9 -8
- data/lib/shrine/attacher.rb +20 -10
- data/lib/shrine/attachment.rb +2 -2
- data/lib/shrine/plugins.rb +22 -0
- data/lib/shrine/plugins/activerecord.rb +3 -3
- data/lib/shrine/plugins/add_metadata.rb +20 -5
- data/lib/shrine/plugins/backgrounding.rb +2 -2
- data/lib/shrine/plugins/default_url.rb +1 -1
- data/lib/shrine/plugins/derivation_endpoint.rb +13 -8
- data/lib/shrine/plugins/derivatives.rb +59 -30
- data/lib/shrine/plugins/determine_mime_type.rb +5 -3
- data/lib/shrine/plugins/entity.rb +12 -11
- data/lib/shrine/plugins/instrumentation.rb +12 -18
- data/lib/shrine/plugins/mirroring.rb +8 -8
- data/lib/shrine/plugins/model.rb +3 -3
- data/lib/shrine/plugins/presign_endpoint.rb +16 -4
- data/lib/shrine/plugins/pretty_location.rb +1 -1
- data/lib/shrine/plugins/processing.rb +1 -1
- data/lib/shrine/plugins/refresh_metadata.rb +2 -2
- data/lib/shrine/plugins/remote_url.rb +3 -3
- data/lib/shrine/plugins/remove_attachment.rb +5 -0
- data/lib/shrine/plugins/remove_invalid.rb +10 -5
- data/lib/shrine/plugins/sequel.rb +1 -1
- data/lib/shrine/plugins/store_dimensions.rb +4 -2
- data/lib/shrine/plugins/type_predicates.rb +113 -0
- data/lib/shrine/plugins/upload_endpoint.rb +10 -5
- data/lib/shrine/plugins/upload_options.rb +2 -2
- data/lib/shrine/plugins/url_options.rb +2 -2
- data/lib/shrine/plugins/validation.rb +9 -7
- data/lib/shrine/storage/linter.rb +4 -4
- data/lib/shrine/storage/memory.rb +5 -3
- data/lib/shrine/storage/s3.rb +117 -38
- data/lib/shrine/version.rb +1 -1
- data/shrine.gemspec +8 -8
- metadata +42 -34
@@ -3,14 +3,48 @@ title: Atomic Helpers
|
|
3
3
|
---
|
4
4
|
|
5
5
|
The [`atomic_helpers`][atomic_helpers] plugin provides API for retrieving and
|
6
|
-
persisting attachments in a concurrency-safe way, which is useful
|
7
|
-
the `backgrounding` plugin. The database plugins (`activerecord`
|
8
|
-
implement atomic promotion and atomic persistence on top of this
|
6
|
+
persisting attachments in a concurrency-safe way, which is especially useful
|
7
|
+
when using the `backgrounding` plugin. The database plugins (`activerecord`
|
8
|
+
and `sequel`) implement atomic promotion and atomic persistence on top of this
|
9
|
+
plugin.
|
9
10
|
|
10
11
|
```rb
|
11
12
|
plugin :atomic_helpers
|
12
13
|
```
|
13
14
|
|
15
|
+
## Problem Statement
|
16
|
+
|
17
|
+
What happens if two different processors (web workers, background jobs,
|
18
|
+
command-line executions, whatever) try to edit a shrine attachment
|
19
|
+
concurrently? The kinds of edits typically made include: "promoting a file",
|
20
|
+
moving it to a different storage and persisting that change in the model;
|
21
|
+
adding or changing a derivative; adding or changing a metadata element.
|
22
|
+
|
23
|
+
There are two main categories of "race condition":
|
24
|
+
|
25
|
+
1. The file could be switched out from under you. If you were promoting a file,
|
26
|
+
but some other process has *changed* the attachment, you don't want to
|
27
|
+
overwrite it with the promomoted version of the *prior* attacchment. Likewise,
|
28
|
+
if you were adding metadata or a derivative, they would be corresponding to a
|
29
|
+
certain attachment, and you don't want to accidentally add them to a now changed
|
30
|
+
attacchment for which they are inappropriate.
|
31
|
+
|
32
|
+
2. Overwriting each other's edits. Since all shrine (meta)data is stored in a
|
33
|
+
single JSON hash, standard implementations will write the entire JSON hash at
|
34
|
+
once to a rdbms column or other store. If two processes both read in the hash,
|
35
|
+
make a change to different keys in it, and then write it back out, the second
|
36
|
+
process to write will 'win' and overwrite changes made by the first.
|
37
|
+
|
38
|
+
The atomic helpers give you tools to avoid both of these sorts of race
|
39
|
+
conditions, under conditions of concurrent editing.
|
40
|
+
|
41
|
+
## High-level ORM helpers
|
42
|
+
|
43
|
+
If you are using the `sequel` or `activerecord` plugins, they give you two
|
44
|
+
higher-level helpers: `atomic_persist` and `atomic_promote`. See the
|
45
|
+
[persistence] documentation for more.
|
46
|
+
|
47
|
+
|
14
48
|
## Retrieving
|
15
49
|
|
16
50
|
The `Attacher.retrieve` method provided by the plugin instantiates an attacher
|
@@ -177,3 +211,7 @@ end
|
|
177
211
|
```
|
178
212
|
|
179
213
|
[atomic_helpers]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/atomic_helpers.rb
|
214
|
+
|
215
|
+
[persistence]: https://shrinerb.com/docs/plugins/persistence
|
216
|
+
|
217
|
+
[backgrounding]: https://shrinerb.com/docs/plugins/backgrounding
|
@@ -187,12 +187,22 @@ and make the execution synchronous, you can override them on the attacher level
|
|
187
187
|
and call the default behaviour:
|
188
188
|
|
189
189
|
```rb
|
190
|
-
photo.image_attacher.promote_block
|
191
|
-
photo.image_attacher.destroy_block
|
190
|
+
photo.image_attacher.promote_block { promote } # promote synchronously
|
191
|
+
photo.image_attacher.destroy_block { destroy } # destroy synchronously
|
192
192
|
|
193
193
|
# ... now promotion and deletion will be synchronous ...
|
194
194
|
```
|
195
195
|
|
196
|
+
You can also do this on the class level if you want to disable backgrounding
|
197
|
+
that was set up by a superclass:
|
198
|
+
|
199
|
+
```rb
|
200
|
+
class MyUploader < Shrine
|
201
|
+
Attacher.promote_block { promote } # promote synchronously
|
202
|
+
Attacher.destroy_block { destroy } # destroy synchronously
|
203
|
+
end
|
204
|
+
```
|
205
|
+
|
196
206
|
[backgrounding]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/backgrounding.rb
|
197
207
|
[derivatives]: https://shrinerb.com/docs/plugins/derivatives
|
198
208
|
[atomic_helpers]: https://shrinerb.com/docs/plugins/atomic_helpers
|
data/doc/plugins/column.md
CHANGED
@@ -66,23 +66,48 @@ If you want to load attachment from a Hash, use `Attacher.from_data` or
|
|
66
66
|
|
67
67
|
## Serializer
|
68
68
|
|
69
|
-
By default the `JSON` standard library is used
|
70
|
-
|
71
|
-
|
69
|
+
By default, the `JSON` standard library is used for serializing hash data. With
|
70
|
+
the [`model`][model] and [`entity`][entity] plugin, the data is serialized
|
71
|
+
before writing to and deserialized after reading from the data attribute.
|
72
|
+
|
73
|
+
You can also use your own serializer via the `:serializer` option. The
|
74
|
+
serializer object needs to implement `#dump` and `#load` methods:
|
75
|
+
|
76
|
+
```rb
|
77
|
+
class MyDataSerializer
|
78
|
+
def self.dump(data)
|
79
|
+
data #=> { "id" => "...", "storage" => "...", "metadata" => { ... } }
|
80
|
+
|
81
|
+
JSON.generate(data) # serialize data, e.g. into JSON
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.load(data)
|
85
|
+
data #=> '{"id":"...", "storage":"...", "metadata": {...}}'
|
86
|
+
|
87
|
+
JSON.parse(data) # deserialize data, e.g. from JSON
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
plugin :column, serializer: MyDataSerializer
|
92
|
+
```
|
93
|
+
|
94
|
+
Some serialization libraries such as [Oj] and [MessagePack] already implement
|
95
|
+
this interface, which simplifies the configuration:
|
72
96
|
|
73
97
|
```rb
|
74
|
-
require "oj"
|
98
|
+
require "oj" # https://github.com/ohler55/oj
|
75
99
|
|
76
|
-
plugin :column, serializer: Oj
|
100
|
+
plugin :column, serializer: Oj
|
77
101
|
```
|
78
102
|
|
79
|
-
If you want to disable serialization, you can set
|
103
|
+
If you want to disable serialization and work with hashes directly, you can set
|
104
|
+
`:serializer` to `nil`:
|
80
105
|
|
81
106
|
```rb
|
82
107
|
plugin :column, serializer: nil # disable serialization
|
83
108
|
```
|
84
109
|
|
85
|
-
|
110
|
+
The serializer can also be changed for a particular attacher instance:
|
86
111
|
|
87
112
|
```rb
|
88
113
|
Shrine::Attacher.new(column_serializer: Oj) # use custom serializer
|
@@ -90,3 +115,7 @@ Shrine::Attacher.new(column_serializer: nil) # disable serialization
|
|
90
115
|
```
|
91
116
|
|
92
117
|
[column]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/column.rb
|
118
|
+
[model]: https://shrinerb.com/docs/plugins/model
|
119
|
+
[entity]: https://shrinerb.com/docs/plugins/entity
|
120
|
+
[Oj]: https://github.com/ohler55/oj
|
121
|
+
[MessagePack]: https://github.com/msgpack/msgpack-ruby
|
data/doc/plugins/default_url.md
CHANGED
@@ -8,7 +8,7 @@ returned when there is no attached file.
|
|
8
8
|
```rb
|
9
9
|
plugin :default_url
|
10
10
|
|
11
|
-
Attacher.default_url do
|
11
|
+
Attacher.default_url do |**options|
|
12
12
|
"/#{name}/missing.jpg"
|
13
13
|
end
|
14
14
|
```
|
@@ -28,7 +28,7 @@ Any URL options passed will be available in the default URL block:
|
|
28
28
|
attacher.url(foo: "bar")
|
29
29
|
```
|
30
30
|
```rb
|
31
|
-
Attacher.default_url do
|
31
|
+
Attacher.default_url do |**options|
|
32
32
|
options #=> { foo: "bar" }
|
33
33
|
end
|
34
34
|
```
|
@@ -37,12 +37,15 @@ The default URL block is evaluated in the context of an instance of
|
|
37
37
|
`Shrine::Attacher`.
|
38
38
|
|
39
39
|
```rb
|
40
|
-
Attacher.default_url do
|
40
|
+
Attacher.default_url do |**options|
|
41
41
|
self #=> #<Shrine::Attacher>
|
42
42
|
|
43
|
+
file #=> #<Shrine::UploadedFile>
|
43
44
|
name #=> :avatar
|
44
45
|
record #=> #<User>
|
45
46
|
context #=> { ... }
|
47
|
+
|
48
|
+
# ...
|
46
49
|
end
|
47
50
|
```
|
48
51
|
|
data/doc/plugins/derivatives.md
CHANGED
@@ -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
|
|
@@ -38,49 +38,43 @@ class ImageUploader < Shrine
|
|
38
38
|
end
|
39
39
|
```
|
40
40
|
```rb
|
41
|
-
class Photo < Model(:image_data)
|
42
|
-
include ImageUploader::Attachment(:image)
|
43
|
-
end
|
44
|
-
```
|
45
|
-
```rb
|
46
41
|
photo = Photo.new(image: file)
|
47
|
-
photo.image_derivatives! #
|
42
|
+
photo.image_derivatives! # creates derivatives
|
48
43
|
photo.save
|
49
44
|
```
|
50
45
|
|
51
|
-
|
52
|
-
route make sure to create derivatives for new attachments:
|
46
|
+
You can then retrieve the URL of a processed derivative:
|
53
47
|
|
54
48
|
```rb
|
55
|
-
photo.
|
56
|
-
```
|
57
|
-
|
58
|
-
You can then retrieve created derivatives as follows:
|
59
|
-
|
60
|
-
```rb
|
61
|
-
photo.image(:large) #=> #<Shrine::UploadedFile ...>
|
62
|
-
photo.image(:large).url #=> "https://s3.amazonaws.com/path/to/large.jpg"
|
63
|
-
photo.image(:large).size #=> 43843
|
64
|
-
photo.image(:large).mime_type #=> "image/jpeg"
|
49
|
+
photo.image_url(:large) #=> "https://s3.amazonaws.com/path/to/large.jpg"
|
65
50
|
```
|
66
51
|
|
67
|
-
The derivatives data is stored in the
|
68
|
-
|
52
|
+
The derivatives data is stored in the `<attachment>_data` column alongside the
|
53
|
+
main file:
|
69
54
|
|
70
55
|
```rb
|
71
56
|
photo.image_data #=>
|
72
57
|
# {
|
73
|
-
# "id": "original.jpg",
|
58
|
+
# "id": "path/to/original.jpg",
|
74
59
|
# "store": "store",
|
75
60
|
# "metadata": { ... },
|
76
61
|
# "derivatives": {
|
77
|
-
# "small": { "id": "small.jpg", "storage": "store", "metadata": { ... } },
|
78
|
-
# "medium": { "id": "medium.jpg", "storage": "store", "metadata": { ... } },
|
79
|
-
# "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": { ... } },
|
80
65
|
# }
|
81
66
|
# }
|
82
67
|
```
|
83
68
|
|
69
|
+
And they can be retrieved as `Shrine::UploadedFile` objects:
|
70
|
+
|
71
|
+
```rb
|
72
|
+
photo.image(:large) #=> #<Shrine::UploadedFile id="path/to/large.jpg" storage=:store metadata={...}>
|
73
|
+
photo.image(:large).url #=> "https://s3.amazonaws.com/path/to/large.jpg"
|
74
|
+
photo.image(:large).size #=> 5825949
|
75
|
+
photo.image(:large).mime_type #=> "image/jpeg"
|
76
|
+
```
|
77
|
+
|
84
78
|
## Retrieving derivatives
|
85
79
|
|
86
80
|
The list of stored derivatives can be retrieved with `#<name>_derivatives`:
|
@@ -135,7 +129,7 @@ You can use the [`default_url`][default_url] plugin to set up URL fallbacks:
|
|
135
129
|
|
136
130
|
```rb
|
137
131
|
Attacher.default_url do |derivative: nil, **|
|
138
|
-
"
|
132
|
+
"/fallbacks/#{derivative}.jpg" if derivative
|
139
133
|
end
|
140
134
|
```
|
141
135
|
```rb
|
@@ -203,6 +197,19 @@ attacher.create_derivatives(different_source) # pass a different source file
|
|
203
197
|
attacher.create_derivatives(foo: "bar") # pass custom options to the processor
|
204
198
|
```
|
205
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
|
+
|
206
213
|
### Naming processors
|
207
214
|
|
208
215
|
If you want to have multiple processors for an uploader, you can assign each
|
@@ -279,11 +286,14 @@ The storage block is evaluated in the context of a `Shrine::Attacher` instance:
|
|
279
286
|
|
280
287
|
```rb
|
281
288
|
Attacher.derivatives_storage do |derivative|
|
282
|
-
self
|
289
|
+
self #=> #<Shrine::Attacher>
|
283
290
|
|
291
|
+
file #=> #<Shrine::UploadedFile>
|
284
292
|
record #=> #<Photo>
|
285
293
|
name #=> :image
|
286
294
|
context #=> { ... }
|
295
|
+
|
296
|
+
# ...
|
287
297
|
end
|
288
298
|
```
|
289
299
|
|
@@ -352,6 +362,7 @@ which allows you to change your processing logic based on the record data.
|
|
352
362
|
Attacher.derivatives :my_processor do |original|
|
353
363
|
self #=> #<Shrine::Attacher>
|
354
364
|
|
365
|
+
file #=> #<Shrine::UploadedFile>
|
355
366
|
record #=> #<Photo>
|
356
367
|
name #=> :image
|
357
368
|
context #=> { ... }
|
@@ -390,7 +401,8 @@ attacher.process_derivatives(:my_processor) # downloads attached file and passes
|
|
390
401
|
|
391
402
|
If you want to use a different source file, you can pass it in to the process
|
392
403
|
call. Typically you'd pass a local file on disk. If you pass a
|
393
|
-
`Shrine::UploadedFile` object, it will be
|
404
|
+
`Shrine::UploadedFile` object or another IO-like object, it will be
|
405
|
+
automatically downloaded/copied to a local TempFile on disk.
|
394
406
|
|
395
407
|
```rb
|
396
408
|
# named processor:
|
@@ -410,17 +422,31 @@ attacher.file.download do |original|
|
|
410
422
|
end
|
411
423
|
```
|
412
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
|
+
|
413
439
|
## Adding derivatives
|
414
440
|
|
415
441
|
If you already have processed files that you want to save, you can do that with
|
416
442
|
`Attacher#add_derivatives`:
|
417
443
|
|
418
444
|
```rb
|
419
|
-
attacher.add_derivatives(
|
445
|
+
attacher.add_derivatives({
|
420
446
|
one: file_1,
|
421
447
|
two: file_2,
|
422
448
|
# ...
|
423
|
-
)
|
449
|
+
})
|
424
450
|
|
425
451
|
attacher.derivatives #=>
|
426
452
|
# {
|
@@ -434,7 +460,7 @@ New derivatives will be merged with existing ones:
|
|
434
460
|
|
435
461
|
```rb
|
436
462
|
attacher.derivatives #=> { one: #<Shrine::UploadedFile> }
|
437
|
-
attacher.add_derivatives(two: two_file)
|
463
|
+
attacher.add_derivatives({ two: two_file })
|
438
464
|
attacher.derivatives #=> { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> }
|
439
465
|
```
|
440
466
|
|
@@ -442,7 +468,7 @@ The merging is deep, so the following will work as well:
|
|
442
468
|
|
443
469
|
```rb
|
444
470
|
attacher.derivatives #=> { nested: { one: #<Shrine::UploadedFile> } }
|
445
|
-
attacher.add_derivatives(nested: { two: two_file })
|
471
|
+
attacher.add_derivatives({ nested: { two: two_file } })
|
446
472
|
attacher.derivatives #=> { nested: { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> } }
|
447
473
|
```
|
448
474
|
|
@@ -453,6 +479,11 @@ For adding a single derivative, you can also use the singular
|
|
453
479
|
attacher.add_derivative(:thumb, thumbnail_file)
|
454
480
|
```
|
455
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
|
+
|
456
487
|
Any options passed to `Attacher#add_derivative(s)` will be forwarded to
|
457
488
|
[`Attacher#upload_derivatives`](#uploading-derivatives).
|
458
489
|
|
@@ -469,11 +500,11 @@ If you want to upload processed files without setting them, you can use
|
|
469
500
|
`Attacher#upload_derivatives`:
|
470
501
|
|
471
502
|
```rb
|
472
|
-
derivatives = attacher.upload_derivatives(
|
503
|
+
derivatives = attacher.upload_derivatives({
|
473
504
|
one: file_1,
|
474
505
|
two: file_2,
|
475
506
|
# ...
|
476
|
-
)
|
507
|
+
})
|
477
508
|
|
478
509
|
derivatives #=>
|
479
510
|
# {
|
@@ -549,7 +580,7 @@ If you want to save already uploaded derivatives, you can use
|
|
549
580
|
|
550
581
|
```rb
|
551
582
|
attacher.derivatives #=> { one: #<Shrine::UploadedFile> }
|
552
|
-
attacher.merge_derivatives attacher.upload_derivatives(two: two_file)
|
583
|
+
attacher.merge_derivatives attacher.upload_derivatives({ two: two_file })
|
553
584
|
attacher.derivatives #=> { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> }
|
554
585
|
```
|
555
586
|
|
@@ -557,10 +588,15 @@ This does a deep merge, so the following will work as well:
|
|
557
588
|
|
558
589
|
```rb
|
559
590
|
attacher.derivatives #=> { nested: { one: #<Shrine::UploadedFile> } }
|
560
|
-
attacher.merge_derivatives attacher.upload_derivatives(nested: { two: two_file })
|
591
|
+
attacher.merge_derivatives attacher.upload_derivatives({ nested: { two: two_file } })
|
561
592
|
attacher.derivatives #=> { nested: { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> } }
|
562
593
|
```
|
563
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
|
+
|
564
600
|
The `Attacher#merge_derivatives` method is thread-safe.
|
565
601
|
|
566
602
|
### Setting derivatives
|
@@ -570,7 +606,7 @@ If instead of adding you want to *override* existing derivatives, you can use
|
|
570
606
|
|
571
607
|
```rb
|
572
608
|
attacher.derivatives #=> { one: #<Shrine::UploadedFile> }
|
573
|
-
attacher.set_derivatives attacher.upload_derivatives(two: two_file)
|
609
|
+
attacher.set_derivatives attacher.upload_derivatives({ two: two_file })
|
574
610
|
attacher.derivatives #=> { two: #<Shrine::UploadedFile> }
|
575
611
|
```
|
576
612
|
|
@@ -678,7 +714,7 @@ You can store derivatives even if there is no main attached file:
|
|
678
714
|
|
679
715
|
```rb
|
680
716
|
attacher.file #=> nil
|
681
|
-
attacher.add_derivatives(one: one_file, two: two_file)
|
717
|
+
attacher.add_derivatives({ one: one_file, two: two_file })
|
682
718
|
attacher.data #=>
|
683
719
|
# {
|
684
720
|
# "derivatives" => {
|
@@ -756,11 +792,13 @@ plugin :derivatives
|
|
756
792
|
Processing derivatives will trigger a `derivatives.shrine` event with the
|
757
793
|
following payload:
|
758
794
|
|
759
|
-
| Key | Description
|
760
|
-
| :-- | :----
|
761
|
-
| `:processor` | Name of the derivatives processor
|
762
|
-
| `:processor_options` | Any options passed to the processor
|
763
|
-
| `:
|
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 |
|
764
802
|
|
765
803
|
A default log subscriber is added as well which logs these events:
|
766
804
|
|
@@ -776,7 +814,7 @@ plugin :derivatives, log_subscriber: -> (event) {
|
|
776
814
|
}
|
777
815
|
```
|
778
816
|
```
|
779
|
-
{"name":"derivatives","duration":2133,"processor":"thumbnails","processor_options":{},"uploader":"ImageUploader"}
|
817
|
+
{"name":"derivatives","duration":2133,"processor":"thumbnails","processor_options":{},"io":"#<File:...>","uploader":"ImageUploader"}
|
780
818
|
```
|
781
819
|
|
782
820
|
Or disable logging altogether:
|
@@ -785,6 +823,7 @@ Or disable logging altogether:
|
|
785
823
|
plugin :derivatives, log_subscriber: nil
|
786
824
|
```
|
787
825
|
|
826
|
+
[derivatives]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/derivatives.rb
|
788
827
|
[default_url]: https://shrinerb.com/docs/plugins/default_url
|
789
828
|
[entity]: https://shrinerb.com/docs/plugins/entity
|
790
829
|
[model]: https://shrinerb.com/docs/plugins/model
|