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,839 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Derivatives
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
The [`derivatives`][derivatives] plugin allows storing processed files ("derivatives") alongside
|
|
6
|
+
the main attached file. The processed file data will be saved together with the
|
|
7
|
+
main attachment data in the same record attribute.
|
|
8
|
+
|
|
9
|
+
```rb
|
|
10
|
+
Shrine.plugin :derivatives
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick start
|
|
14
|
+
|
|
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.
|
|
18
|
+
|
|
19
|
+
Here is an example of generating image thumbnails:
|
|
20
|
+
|
|
21
|
+
```rb
|
|
22
|
+
# Gemfile
|
|
23
|
+
gem "image_processing", "~> 1.8"
|
|
24
|
+
```
|
|
25
|
+
```rb
|
|
26
|
+
require "image_processing/mini_magick"
|
|
27
|
+
|
|
28
|
+
class ImageUploader < Shrine
|
|
29
|
+
Attacher.derivatives do |original|
|
|
30
|
+
magick = ImageProcessing::MiniMagick.source(original)
|
|
31
|
+
|
|
32
|
+
{
|
|
33
|
+
small: magick.resize_to_limit!(300, 300),
|
|
34
|
+
medium: magick.resize_to_limit!(500, 500),
|
|
35
|
+
large: magick.resize_to_limit!(800, 800),
|
|
36
|
+
}
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
```
|
|
40
|
+
```rb
|
|
41
|
+
photo = Photo.new(image: file)
|
|
42
|
+
photo.image_derivatives! # creates derivatives
|
|
43
|
+
photo.save
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
You can then retrieve the URL of a processed derivative:
|
|
47
|
+
|
|
48
|
+
```rb
|
|
49
|
+
photo.image_url(:large) #=> "https://s3.amazonaws.com/path/to/large.jpg"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The derivatives data is stored in the `<attachment>_data` column alongside the
|
|
53
|
+
main file:
|
|
54
|
+
|
|
55
|
+
```rb
|
|
56
|
+
photo.image_data #=>
|
|
57
|
+
# {
|
|
58
|
+
# "id": "path/to/original.jpg",
|
|
59
|
+
# "store": "store",
|
|
60
|
+
# "metadata": { ... },
|
|
61
|
+
# "derivatives": {
|
|
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": { ... } },
|
|
65
|
+
# }
|
|
66
|
+
# }
|
|
67
|
+
```
|
|
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
|
+
|
|
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/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.
|
|
180
|
+
|
|
181
|
+
```rb
|
|
182
|
+
attacher.file #=> #<Shrine::UploadedFile id="original.jpg" storage=:store ...>
|
|
183
|
+
attacher.create_derivatives # calls default processor and uploads results
|
|
184
|
+
attacher.derivatives #=>
|
|
185
|
+
# {
|
|
186
|
+
# small: #<Shrine::UploadedFile id="small.jpg" storage=:store ...>,
|
|
187
|
+
# medium: #<Shrine::UploadedFile id="medium.jpg" storage=:store ...>,
|
|
188
|
+
# large: #<Shrine::UploadedFile id="large.jpg" storage=:store ...>,
|
|
189
|
+
# }
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Any additional arguments are forwarded to
|
|
193
|
+
[`Attacher#process_derivatives`](#processing-derivatives):
|
|
194
|
+
|
|
195
|
+
```rb
|
|
196
|
+
attacher.create_derivatives(different_source) # pass a different source file
|
|
197
|
+
attacher.create_derivatives(foo: "bar") # pass custom options to the processor
|
|
198
|
+
```
|
|
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
|
+
|
|
213
|
+
### Naming processors
|
|
214
|
+
|
|
215
|
+
If you want to have multiple processors for an uploader, you can assign each
|
|
216
|
+
processor a name:
|
|
217
|
+
|
|
218
|
+
```rb
|
|
219
|
+
class ImageUploader < Shrine
|
|
220
|
+
Attacher.derivatives :thumbnails do |original|
|
|
221
|
+
{ large: ..., medium: ..., small: ... }
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
Attacher.derivatives :crop do |original|
|
|
225
|
+
{ cropped: ... }
|
|
226
|
+
end
|
|
227
|
+
end
|
|
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
|
+
|
|
233
|
+
```rb
|
|
234
|
+
attacher.create_derivatives(:thumbnails)
|
|
235
|
+
attacher.derivatives #=> { large: ..., medium: ..., small: ... }
|
|
236
|
+
|
|
237
|
+
attacher.create_derivatives(:crop)
|
|
238
|
+
attacher.derivatives #=> { large: ..., medium: ..., small: ..., cropped: ... }
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Derivatives storage
|
|
242
|
+
|
|
243
|
+
By default, derivatives are uploaded to the permanent storage of the attacher.
|
|
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
|
|
253
|
+
option:
|
|
254
|
+
|
|
255
|
+
```rb
|
|
256
|
+
plugin :derivatives, storage: :other_store
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
The storage can be dynamic based on the derivative name:
|
|
260
|
+
|
|
261
|
+
```rb
|
|
262
|
+
plugin :derivatives, storage: -> (derivative) do
|
|
263
|
+
if derivative == :thumb
|
|
264
|
+
:thumbnail_store
|
|
265
|
+
else
|
|
266
|
+
:store
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
You can also set this option with `Attacher.derivatives_storage`:
|
|
272
|
+
|
|
273
|
+
```rb
|
|
274
|
+
Attacher.derivatives_storage :other_store
|
|
275
|
+
# or
|
|
276
|
+
Attacher.derivatives_storage do |derivative|
|
|
277
|
+
if derivative == :thumb
|
|
278
|
+
:thumbnail_store
|
|
279
|
+
else
|
|
280
|
+
:store
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
The storage block is evaluated in the context of a `Shrine::Attacher` instance:
|
|
286
|
+
|
|
287
|
+
```rb
|
|
288
|
+
Attacher.derivatives_storage do |derivative|
|
|
289
|
+
self #=> #<Shrine::Attacher>
|
|
290
|
+
|
|
291
|
+
file #=> #<Shrine::UploadedFile>
|
|
292
|
+
record #=> #<Photo>
|
|
293
|
+
name #=> :image
|
|
294
|
+
context #=> { ... }
|
|
295
|
+
|
|
296
|
+
# ...
|
|
297
|
+
end
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Nesting derivatives
|
|
301
|
+
|
|
302
|
+
Derivatives can be nested to any level, using both hashes and arrays, but the
|
|
303
|
+
top-level object must be a hash.
|
|
304
|
+
|
|
305
|
+
```rb
|
|
306
|
+
Attacher.derivatives :tiff do |original|
|
|
307
|
+
{
|
|
308
|
+
thumbnail: {
|
|
309
|
+
small: small,
|
|
310
|
+
medium: medium,
|
|
311
|
+
large: large,
|
|
312
|
+
},
|
|
313
|
+
layers: [
|
|
314
|
+
layer_1,
|
|
315
|
+
layer_2,
|
|
316
|
+
# ...
|
|
317
|
+
]
|
|
318
|
+
}
|
|
319
|
+
end
|
|
320
|
+
```
|
|
321
|
+
```rb
|
|
322
|
+
attacher.derivatives #=>
|
|
323
|
+
# {
|
|
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
|
+
# ]
|
|
334
|
+
# }
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## Processing derivatives
|
|
338
|
+
|
|
339
|
+
A derivatives processor block takes the original file, and is expected to
|
|
340
|
+
return a hash of processed files (it can be [nested](#nesting-derivatives)).
|
|
341
|
+
|
|
342
|
+
```rb
|
|
343
|
+
Attacher.derivatives :my_processor do |original|
|
|
344
|
+
# return a hash of processed files
|
|
345
|
+
end
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
The `Attacher#create_derivatives` method internally calls
|
|
349
|
+
`Attacher#process_derivatives`, which in turn calls the processor:
|
|
350
|
+
|
|
351
|
+
```rb
|
|
352
|
+
files = attacher.process_derivatives(:my_processor)
|
|
353
|
+
attacher.add_derivatives(files)
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### Dynamic processing
|
|
357
|
+
|
|
358
|
+
The processor block is evaluated in context of the `Shrine::Attacher` instance,
|
|
359
|
+
which allows you to change your processing logic based on the record data.
|
|
360
|
+
|
|
361
|
+
```rb
|
|
362
|
+
Attacher.derivatives :my_processor do |original|
|
|
363
|
+
self #=> #<Shrine::Attacher>
|
|
364
|
+
|
|
365
|
+
file #=> #<Shrine::UploadedFile>
|
|
366
|
+
record #=> #<Photo>
|
|
367
|
+
name #=> :image
|
|
368
|
+
context #=> { ... }
|
|
369
|
+
|
|
370
|
+
# ...
|
|
371
|
+
end
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
Moreover, any options passed to `Attacher#process_derivatives` will be
|
|
375
|
+
forwarded to the processor:
|
|
376
|
+
|
|
377
|
+
```rb
|
|
378
|
+
attacher.process_derivatives(:my_processor, foo: "bar")
|
|
379
|
+
```
|
|
380
|
+
```rb
|
|
381
|
+
Attacher.derivatives :my_processor do |original, **options|
|
|
382
|
+
options #=> { :foo => "bar" }
|
|
383
|
+
# ...
|
|
384
|
+
end
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### Source file
|
|
388
|
+
|
|
389
|
+
By default, the `Attacher#process_derivatives` method will download the
|
|
390
|
+
attached file and pass it to the processor:
|
|
391
|
+
|
|
392
|
+
```rb
|
|
393
|
+
Attacher.derivatives :my_processor do |original|
|
|
394
|
+
original #=> #<File:...>
|
|
395
|
+
# ...
|
|
396
|
+
end
|
|
397
|
+
```
|
|
398
|
+
```rb
|
|
399
|
+
attacher.process_derivatives(:my_processor) # downloads attached file and passes it to the processor
|
|
400
|
+
```
|
|
401
|
+
|
|
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:
|
|
417
|
+
|
|
418
|
+
```rb
|
|
419
|
+
attacher.file.download do |original|
|
|
420
|
+
attacher.process_derivatives(:thumbnails, original)
|
|
421
|
+
attacher.process_derivatives(:colors, original)
|
|
422
|
+
end
|
|
423
|
+
```
|
|
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
|
+
|
|
439
|
+
## Adding derivatives
|
|
440
|
+
|
|
441
|
+
If you already have processed files that you want to save, you can do that with
|
|
442
|
+
`Attacher#add_derivatives`:
|
|
443
|
+
|
|
444
|
+
```rb
|
|
445
|
+
attacher.add_derivatives({
|
|
446
|
+
one: file_1,
|
|
447
|
+
two: file_2,
|
|
448
|
+
# ...
|
|
449
|
+
})
|
|
450
|
+
|
|
451
|
+
attacher.derivatives #=>
|
|
452
|
+
# {
|
|
453
|
+
# one: #<Shrine::UploadedFile>,
|
|
454
|
+
# two: #<Shrine::UploadedFile>,
|
|
455
|
+
# ...
|
|
456
|
+
# }
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
New derivatives will be merged with existing ones:
|
|
460
|
+
|
|
461
|
+
```rb
|
|
462
|
+
attacher.derivatives #=> { one: #<Shrine::UploadedFile> }
|
|
463
|
+
attacher.add_derivatives({ two: two_file })
|
|
464
|
+
attacher.derivatives #=> { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> }
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
The merging is deep, so the following will work as well:
|
|
468
|
+
|
|
469
|
+
```rb
|
|
470
|
+
attacher.derivatives #=> { nested: { one: #<Shrine::UploadedFile> } }
|
|
471
|
+
attacher.add_derivatives({ nested: { two: two_file } })
|
|
472
|
+
attacher.derivatives #=> { nested: { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> } }
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
For adding a single derivative, you can also use the singular
|
|
476
|
+
`Attacher#add_derivative`:
|
|
477
|
+
|
|
478
|
+
```rb
|
|
479
|
+
attacher.add_derivative(:thumb, thumbnail_file)
|
|
480
|
+
```
|
|
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
|
+
|
|
487
|
+
Any options passed to `Attacher#add_derivative(s)` will be forwarded to
|
|
488
|
+
[`Attacher#upload_derivatives`](#uploading-derivatives).
|
|
489
|
+
|
|
490
|
+
```rb
|
|
491
|
+
attacher.add_derivative(:thumb, thumbnail_file, storage: :thumbnails_store) # specify destination storage
|
|
492
|
+
attacher.add_derivative(:thumb, thumbnail_file, upload_options: { acl: "public-read" }) # pass uploader options
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
The `Attacher#add_derivative(s)` methods are thread-safe.
|
|
496
|
+
|
|
497
|
+
## Uploading derivatives
|
|
498
|
+
|
|
499
|
+
If you want to upload processed files without setting them, you can use
|
|
500
|
+
`Attacher#upload_derivatives`:
|
|
501
|
+
|
|
502
|
+
```rb
|
|
503
|
+
derivatives = attacher.upload_derivatives({
|
|
504
|
+
one: file_1,
|
|
505
|
+
two: file_2,
|
|
506
|
+
# ...
|
|
507
|
+
})
|
|
508
|
+
|
|
509
|
+
derivatives #=>
|
|
510
|
+
# {
|
|
511
|
+
# one: #<Shrine::UploadedFile>,
|
|
512
|
+
# two: #<Shrine::UploadedFile>,
|
|
513
|
+
# ...
|
|
514
|
+
# }
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
For uploading a single derivative, you can also use the singular
|
|
518
|
+
`Attacher#upload_derivative`:
|
|
519
|
+
|
|
520
|
+
```rb
|
|
521
|
+
attacher.upload_derivative(:thumb, thumbnail_file)
|
|
522
|
+
#=> #<Shrine::UploadedFile>
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
### Uploader options
|
|
526
|
+
|
|
527
|
+
You can specify the destination storage by passing `:storage` option to
|
|
528
|
+
`Attacher#upload_derivative(s)`. This will override the [default derivatives
|
|
529
|
+
storage](#derivatives-storage) setting.
|
|
530
|
+
|
|
531
|
+
```rb
|
|
532
|
+
attacher.upload_derivative(:thumb, thumnbail_file, storage: :other_store)
|
|
533
|
+
#=> #<Shrine::UploadedFile @id="thumb.jpg" @storage_key=:other_store ...>
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
Any other options will be forwarded to the uploader:
|
|
537
|
+
|
|
538
|
+
```rb
|
|
539
|
+
attacher.upload_derivative :thumb, thumbnail_file,
|
|
540
|
+
upload_options: { acl: "public-read" },
|
|
541
|
+
metadata: { "foo" => "bar" }),
|
|
542
|
+
location: "path/to/derivative"
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
The `:derivative` name is automatically passed to the uploader:
|
|
546
|
+
|
|
547
|
+
```rb
|
|
548
|
+
class MyUploader < Shrine
|
|
549
|
+
plugin :add_metadata
|
|
550
|
+
|
|
551
|
+
add_metadata :md5 do |io, derivative: nil, **|
|
|
552
|
+
calculate_signature(io, :md5) unless derivative
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
def generate_location(io, derivative: nil, **)
|
|
556
|
+
"location/for/#{derivative}"
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
plugin :upload_options, store: -> (io, derivative: nil, **) {
|
|
560
|
+
{ acl: "public-read" } if derivative
|
|
561
|
+
}
|
|
562
|
+
end
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
### File deletion
|
|
566
|
+
|
|
567
|
+
Files given to `Attacher#upload_derivative(s)` are assumed to be temporary, so
|
|
568
|
+
for convenience they're automatically closed and unlinked after upload.
|
|
569
|
+
|
|
570
|
+
If you want to disable this behaviour, pass `delete: false`:
|
|
571
|
+
|
|
572
|
+
```rb
|
|
573
|
+
attacher.upload_derivative(:thumb, thumbnail_file, delete: false)
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
## Merging derivatives
|
|
577
|
+
|
|
578
|
+
If you want to save already uploaded derivatives, you can use
|
|
579
|
+
`Attacher#merge_derivatives`:
|
|
580
|
+
|
|
581
|
+
```rb
|
|
582
|
+
attacher.derivatives #=> { one: #<Shrine::UploadedFile> }
|
|
583
|
+
attacher.merge_derivatives attacher.upload_derivatives({ two: two_file })
|
|
584
|
+
attacher.derivatives #=> { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> }
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
This does a deep merge, so the following will work as well:
|
|
588
|
+
|
|
589
|
+
```rb
|
|
590
|
+
attacher.derivatives #=> { nested: { one: #<Shrine::UploadedFile> } }
|
|
591
|
+
attacher.merge_derivatives attacher.upload_derivatives({ nested: { two: two_file } })
|
|
592
|
+
attacher.derivatives #=> { nested: { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> } }
|
|
593
|
+
```
|
|
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
|
+
|
|
600
|
+
The `Attacher#merge_derivatives` method is thread-safe.
|
|
601
|
+
|
|
602
|
+
### Setting derivatives
|
|
603
|
+
|
|
604
|
+
If instead of adding you want to *override* existing derivatives, you can use
|
|
605
|
+
`Attacher#set_derivatives`:
|
|
606
|
+
|
|
607
|
+
```rb
|
|
608
|
+
attacher.derivatives #=> { one: #<Shrine::UploadedFile> }
|
|
609
|
+
attacher.set_derivatives attacher.upload_derivatives({ two: two_file })
|
|
610
|
+
attacher.derivatives #=> { two: #<Shrine::UploadedFile> }
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
If you're using the [`model`][model] plugin, this method will trigger writing
|
|
614
|
+
derivatives data into the column attribute.
|
|
615
|
+
|
|
616
|
+
## Promoting derivatives
|
|
617
|
+
|
|
618
|
+
Any assigned derivatives that are uploaded to temporary storage will be
|
|
619
|
+
automatically uploaded to permanent storage on `Attacher#promote`.
|
|
620
|
+
|
|
621
|
+
```rb
|
|
622
|
+
attacher.derivatives[:one].storage_key #=> :cache
|
|
623
|
+
attacher.promote
|
|
624
|
+
attacher.derivatives[:one].storage_key #=> :store
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
If you want more control over derivatives promotion, you can use
|
|
628
|
+
`Attacher#promote_derivatives`. Any additional options passed to it are
|
|
629
|
+
forwarded to the uploader.
|
|
630
|
+
|
|
631
|
+
```rb
|
|
632
|
+
attacher.derivatives[:one].storage_key #=> :cache
|
|
633
|
+
attacher.promote_derivatives(upload_options: { acl: "public-read" })
|
|
634
|
+
attacher.derivatives[:one].storage_key #=> :store
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
## Removing derivatives
|
|
638
|
+
|
|
639
|
+
If you want to manually remove certain derivatives, you can do that with
|
|
640
|
+
`Attacher#remove_derivative`.
|
|
641
|
+
|
|
642
|
+
```rb
|
|
643
|
+
attacher.derivatives #=> { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> }
|
|
644
|
+
attacher.remove_derivative(:two) #=> #<Shrine::UploadedFile> (removed derivative)
|
|
645
|
+
attacher.derivatives #=> { one: #<Shrine::UploadedFile> }
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
You can also use the plural `Attacher#remove_derivatives` for removing multiple
|
|
649
|
+
derivatives:
|
|
650
|
+
|
|
651
|
+
```rb
|
|
652
|
+
attacher.derivatives #=> { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile>, three: #<Shrine::UploadedFile> }
|
|
653
|
+
attacher.remove_derivative(:two, :three) #=> [#<Shrine::UploadedFile>, #<Shrine::UploadedFile>] (removed derivatives)
|
|
654
|
+
attacher.derivatives #=> { one: #<Shrine::UploadedFile> }
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
It's possible to remove nested derivatives as well:
|
|
658
|
+
|
|
659
|
+
```rb
|
|
660
|
+
attacher.derivatives #=> { nested: { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> } }
|
|
661
|
+
attacher.remove_derivative([:nested, :one]) #=> #<Shrine::UploadedFile> (removed derivative)
|
|
662
|
+
attacher.derivatives #=> { nested: { one: #<Shrine::UploadedFile> } }
|
|
663
|
+
```
|
|
664
|
+
|
|
665
|
+
The removed derivatives are not automatically deleted, because it's safer to
|
|
666
|
+
first persist the removal change, and only then perform the deletion.
|
|
667
|
+
|
|
668
|
+
```rb
|
|
669
|
+
derivative = attacher.remove_derivative(:two)
|
|
670
|
+
# ... persist removal change ...
|
|
671
|
+
derivative.delete
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
If you still want to delete the derivative at the time of removal, you can
|
|
675
|
+
pass `delete: true`:
|
|
676
|
+
|
|
677
|
+
```rb
|
|
678
|
+
derivative = attacher.remove_derivative(:two, delete: true)
|
|
679
|
+
derivative.exists? #=> false
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
### Deleting derivatives
|
|
683
|
+
|
|
684
|
+
If you want to delete a collection of derivatives, you can use
|
|
685
|
+
`Attacher#delete_derivatives`:
|
|
686
|
+
|
|
687
|
+
```rb
|
|
688
|
+
derivatives #=> { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> }
|
|
689
|
+
|
|
690
|
+
attacher.delete_derivatives(derivatives)
|
|
691
|
+
|
|
692
|
+
derivatives[:one].exists? #=> false
|
|
693
|
+
derivatives[:two].exists? #=> false
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
Without arguments `Attacher#delete_derivatives` deletes current derivatives:
|
|
697
|
+
|
|
698
|
+
```rb
|
|
699
|
+
attacher.derivatives #=> { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> }
|
|
700
|
+
|
|
701
|
+
attacher.delete_derivatives
|
|
702
|
+
|
|
703
|
+
attacher.derivatives[:one].exists? #=> false
|
|
704
|
+
attacher.derivatives[:two].exists? #=> false
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
Derivatives are automatically deleted on `Attacher#destroy`.
|
|
708
|
+
|
|
709
|
+
## Miscellaneous
|
|
710
|
+
|
|
711
|
+
### Without original
|
|
712
|
+
|
|
713
|
+
You can store derivatives even if there is no main attached file:
|
|
714
|
+
|
|
715
|
+
```rb
|
|
716
|
+
attacher.file #=> nil
|
|
717
|
+
attacher.add_derivatives({ one: one_file, two: two_file })
|
|
718
|
+
attacher.data #=>
|
|
719
|
+
# {
|
|
720
|
+
# "derivatives" => {
|
|
721
|
+
# "one" => { "id" => "...", "storage" => "...", "metadata": { ... } },
|
|
722
|
+
# "two" => { "id" => "...", "storage" => "...", "metadata": { ... } },
|
|
723
|
+
# }
|
|
724
|
+
# }
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
However, note that in this case operations such as promotion and deletion will
|
|
728
|
+
not be automatically triggered in the attachment flow, you'd need to trigger
|
|
729
|
+
them manually as needed.
|
|
730
|
+
|
|
731
|
+
### Iterating derivatives
|
|
732
|
+
|
|
733
|
+
If you want to iterate over a nested hash of derivatives (which can be
|
|
734
|
+
`Shrine::UploadedFile` objects or raw files), you can use
|
|
735
|
+
`Attacher#map_derivative` or `Shrine.map_derivative`:
|
|
736
|
+
|
|
737
|
+
```rb
|
|
738
|
+
derivatives #=>
|
|
739
|
+
# {
|
|
740
|
+
# one: #<Shrine::UploadedFile>,
|
|
741
|
+
# two: { three: #<Shrine::UploadedFile> },
|
|
742
|
+
# four: [#<Shrine::UploadedFile>],
|
|
743
|
+
# }
|
|
744
|
+
|
|
745
|
+
# or Shrine.map_derivative
|
|
746
|
+
attacher.map_derivative(derivatives) do |name, file|
|
|
747
|
+
puts "#{name}, #{file}"
|
|
748
|
+
end
|
|
749
|
+
|
|
750
|
+
# output:
|
|
751
|
+
#
|
|
752
|
+
# :one, #<Shrine::UploadedFile>
|
|
753
|
+
# [:two, :three], #<Shrine::UploadedFile>
|
|
754
|
+
# [:four, 0], #<Shrine::UploadedFile>
|
|
755
|
+
```
|
|
756
|
+
|
|
757
|
+
### Parsing derivatives
|
|
758
|
+
|
|
759
|
+
If you want to directly parse derivatives data written to a record attribute,
|
|
760
|
+
you can use `Shrine.derivatives` (counterpart to `Shrine.uploaded_file`):
|
|
761
|
+
|
|
762
|
+
```rb
|
|
763
|
+
# or MyUploader.derivatives
|
|
764
|
+
derivatives = Shrine.derivatives({
|
|
765
|
+
"one" => { "id" => "...", "storage" => "...", "metadata" => { ... } },
|
|
766
|
+
"two" => { "three" => { "id" => "...", "storage" => "...", "metadata" => { ... } } }
|
|
767
|
+
"four" => [{ "id" => "...", "storage" => "...", "metadata" => { ... } }]
|
|
768
|
+
})
|
|
769
|
+
|
|
770
|
+
derivatives #=>
|
|
771
|
+
# {
|
|
772
|
+
# one: #<Shrine::UploadedFile>,
|
|
773
|
+
# two: { three: #<Shrine::UploadedFile> },
|
|
774
|
+
# four: [#<Shrine::UploadedFile>],
|
|
775
|
+
# }
|
|
776
|
+
```
|
|
777
|
+
|
|
778
|
+
Like `Shrine.uploaded_file`, the `Shrine.derivatives` method accepts data as a
|
|
779
|
+
hash (stringified or symbolized) or a JSON string.
|
|
780
|
+
|
|
781
|
+
### Marshalling
|
|
782
|
+
|
|
783
|
+
The `Attacher` instance uses a mutex to make `Attacher#merge_derivatives`
|
|
784
|
+
thread-safe, which is not marshallable. If you want to be able to marshal the
|
|
785
|
+
attacher instance, you can skip mutex usage:
|
|
786
|
+
|
|
787
|
+
```rb
|
|
788
|
+
plugin :derivatives, mutex: false
|
|
789
|
+
```
|
|
790
|
+
|
|
791
|
+
## Instrumentation
|
|
792
|
+
|
|
793
|
+
If the `instrumentation` plugin has been loaded, the `derivatives` plugin adds
|
|
794
|
+
instrumentation around derivatives processing.
|
|
795
|
+
|
|
796
|
+
```rb
|
|
797
|
+
# instrumentation plugin needs to be loaded *before* derivatives
|
|
798
|
+
plugin :instrumentation
|
|
799
|
+
plugin :derivatives
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
Processing derivatives will trigger a `derivatives.shrine` event with the
|
|
803
|
+
following payload:
|
|
804
|
+
|
|
805
|
+
| Key | Description |
|
|
806
|
+
| :-- | :---- |
|
|
807
|
+
| `:processor` | Name of the derivatives processor |
|
|
808
|
+
| `:processor_options` | Any options passed to the processor |
|
|
809
|
+
| `:io` | The source file passed to the processor |
|
|
810
|
+
| `:attacher` | The attacher instance doing the processing |
|
|
811
|
+
| `:uploader` | The uploader class that sent the event |
|
|
812
|
+
|
|
813
|
+
A default log subscriber is added as well which logs these events:
|
|
814
|
+
|
|
815
|
+
```
|
|
816
|
+
Derivatives (2133ms) – {:processor=>:thumbnails, :processor_options=>{}, :uploader=>ImageUploader}
|
|
817
|
+
```
|
|
818
|
+
|
|
819
|
+
You can also use your own log subscriber:
|
|
820
|
+
|
|
821
|
+
```rb
|
|
822
|
+
plugin :derivatives, log_subscriber: -> (event) {
|
|
823
|
+
Shrine.logger.info JSON.generate(name: event.name, duration: event.duration, **event.payload)
|
|
824
|
+
}
|
|
825
|
+
```
|
|
826
|
+
```
|
|
827
|
+
{"name":"derivatives","duration":2133,"processor":"thumbnails","processor_options":{},"io":"#<File:...>","uploader":"ImageUploader"}
|
|
828
|
+
```
|
|
829
|
+
|
|
830
|
+
Or disable logging altogether:
|
|
831
|
+
|
|
832
|
+
```rb
|
|
833
|
+
plugin :derivatives, log_subscriber: nil
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
[derivatives]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/derivatives.rb
|
|
837
|
+
[default_url]: https://shrinerb.com/docs/plugins/default_url
|
|
838
|
+
[entity]: https://shrinerb.com/docs/plugins/entity
|
|
839
|
+
[model]: https://shrinerb.com/docs/plugins/model
|