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
data/doc/plugins/activerecord.md
CHANGED
|
@@ -1,93 +1,224 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
title: Active Record
|
|
3
|
+
---
|
|
2
4
|
|
|
3
|
-
The [`activerecord`][activerecord] plugin
|
|
4
|
-
|
|
5
|
+
The [`activerecord`][activerecord] plugin adds [Active Record] integration to
|
|
6
|
+
the attachment interface. It is built on top of the [`model`][model] plugin.
|
|
5
7
|
|
|
6
8
|
```rb
|
|
7
|
-
plugin :activerecord
|
|
9
|
+
Shrine.plugin :activerecord
|
|
8
10
|
```
|
|
9
11
|
|
|
10
|
-
##
|
|
12
|
+
## Attachment
|
|
11
13
|
|
|
12
|
-
|
|
14
|
+
Including a `Shrine::Attachment` module into an `ActiveRecord::Base` subclass
|
|
15
|
+
will:
|
|
13
16
|
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
|
|
17
|
+
* add [model] attachment methods
|
|
18
|
+
* add [validations](#validations) and [callbacks](#callbacks) to tie attachment
|
|
19
|
+
process to the record lifecycle
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
```rb
|
|
22
|
+
class Photo < ActiveRecord::Base # has `image_data` column
|
|
23
|
+
include ImageUploader::Attachment(:image) # adds methods, callbacks & validations
|
|
24
|
+
end
|
|
25
|
+
```
|
|
26
|
+
```rb
|
|
27
|
+
photo = Photo.new
|
|
28
|
+
|
|
29
|
+
photo.image = file # cache attachment
|
|
30
|
+
|
|
31
|
+
photo.image #=> #<Shrine::UploadedFile id="bc2e13.jpg" storage=:cache ...>
|
|
32
|
+
photo.image_data #=> '{"id":"bc2e13.jpg","storage":"cache","metadata":{...}}'
|
|
33
|
+
|
|
34
|
+
photo.save # persist, promote attachment, then persist again
|
|
35
|
+
|
|
36
|
+
photo.image #=> #<Shrine::UploadedFile id="397eca.jpg" storage=:store ...>
|
|
37
|
+
photo.image_data #=> '{"id":"397eca.jpg","storage":"store","metadata":{...}}'
|
|
38
|
+
|
|
39
|
+
photo.destroy # delete attachment
|
|
40
|
+
|
|
41
|
+
photo.image.exists? #=> false
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Callbacks
|
|
45
|
+
|
|
46
|
+
#### After Save
|
|
47
|
+
|
|
48
|
+
After a record is saved and the transaction is committed, `Attacher#finalize`
|
|
49
|
+
is called, which promotes cached file to permanent storage and deletes previous
|
|
50
|
+
file if any.
|
|
21
51
|
|
|
22
52
|
```rb
|
|
23
|
-
|
|
24
|
-
|
|
53
|
+
photo = Photo.new
|
|
54
|
+
|
|
55
|
+
photo.image = file
|
|
56
|
+
photo.image.storage_key #=> :cache
|
|
57
|
+
|
|
58
|
+
photo.save
|
|
59
|
+
photo.image.storage_key #=> :store
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
#### After Destroy
|
|
63
|
+
|
|
64
|
+
After a record is destroyed and the transaction is committed,
|
|
65
|
+
`Attacher#destroy_attached` method is called, which deletes stored attached
|
|
66
|
+
file if any.
|
|
67
|
+
|
|
68
|
+
```rb
|
|
69
|
+
photo = Photo.find(photo_id)
|
|
70
|
+
photo.image #=> #<Shrine::UploadedFile>
|
|
71
|
+
photo.image.exists? #=> true
|
|
72
|
+
|
|
73
|
+
photo.destroy
|
|
74
|
+
photo.image.exists? #=> false
|
|
25
75
|
```
|
|
26
76
|
|
|
27
|
-
|
|
28
|
-
`backgrounding` plugin.
|
|
77
|
+
#### Caveats
|
|
29
78
|
|
|
30
|
-
|
|
31
|
-
|
|
79
|
+
Active Record currently has a [bug with transaction callbacks], so if you have
|
|
80
|
+
any "after commit" callbacks, make sure to include Shrine's attachment module
|
|
81
|
+
*after* they have all been defined.
|
|
82
|
+
|
|
83
|
+
#### Overriding callbacks
|
|
84
|
+
|
|
85
|
+
You can override any of the following attacher methods to modify callback
|
|
86
|
+
behaviour:
|
|
87
|
+
|
|
88
|
+
* `Attacher#activerecord_before_save`
|
|
89
|
+
* `Attacher#activerecord_after_save`
|
|
90
|
+
* `Attacher#activerecord_after_destroy`
|
|
32
91
|
|
|
33
92
|
```rb
|
|
34
|
-
class
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if avatar_data_changed? && avatar_attacher.cached?
|
|
39
|
-
# cached
|
|
40
|
-
elsif avatar_data_changed? && avatar_attacher.stored?
|
|
41
|
-
# promoted
|
|
42
|
-
end
|
|
93
|
+
class Shrine::Attacher
|
|
94
|
+
def activerecord_after_save
|
|
95
|
+
super
|
|
96
|
+
# ...
|
|
43
97
|
end
|
|
44
98
|
end
|
|
45
99
|
```
|
|
46
100
|
|
|
47
|
-
|
|
48
|
-
you have any "after commit" callbacks, make sure to include Shrine's attachment
|
|
49
|
-
module *after* they have all been defined.
|
|
101
|
+
#### Skipping Callbacks
|
|
50
102
|
|
|
51
|
-
If you don't want the attachment module to add any callbacks to
|
|
52
|
-
|
|
103
|
+
If you don't want the attachment module to add any callbacks to your model, you
|
|
104
|
+
can set `:callbacks` to `false`:
|
|
53
105
|
|
|
54
106
|
```rb
|
|
55
107
|
plugin :activerecord, callbacks: false
|
|
56
108
|
```
|
|
57
109
|
|
|
58
|
-
|
|
110
|
+
### Validations
|
|
59
111
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
strings, they can also be symbols or symbols and options, which allows them to
|
|
63
|
-
be internationalized together with other ActiveRecord validation messages.
|
|
112
|
+
If you're using the [`validation`][validation] plugin, the attachment module
|
|
113
|
+
will automatically merge attacher errors with model errors.
|
|
64
114
|
|
|
65
115
|
```rb
|
|
66
|
-
class
|
|
116
|
+
class ImageUploader < Shrine
|
|
67
117
|
plugin :validation_helpers
|
|
68
118
|
|
|
69
119
|
Attacher.validate do
|
|
70
|
-
validate_max_size
|
|
120
|
+
validate_max_size 10 * 1024 * 1024
|
|
71
121
|
end
|
|
72
122
|
end
|
|
73
123
|
```
|
|
124
|
+
```rb
|
|
125
|
+
photo = Photo.new
|
|
126
|
+
photo.image = file
|
|
127
|
+
photo.valid?
|
|
128
|
+
photo.errors #=> { image: ["size must not be greater than 10.0 MB"] }
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
#### Attachment Presence
|
|
74
132
|
|
|
75
|
-
If you want to validate presence of the attachment, you can
|
|
76
|
-
|
|
133
|
+
If you want to validate presence of the attachment, you can use Active Record's
|
|
134
|
+
presence validator:
|
|
77
135
|
|
|
78
136
|
```rb
|
|
79
|
-
class
|
|
80
|
-
include ImageUploader::Attachment
|
|
81
|
-
|
|
137
|
+
class Photo < ActiveRecord::Base
|
|
138
|
+
include ImageUploader::Attachment(:image)
|
|
139
|
+
|
|
140
|
+
validates_presence_of :image
|
|
82
141
|
end
|
|
83
142
|
```
|
|
84
143
|
|
|
144
|
+
#### I18n
|
|
145
|
+
|
|
146
|
+
If you want Active Record to translate attacher error messages, you can use
|
|
147
|
+
symbols or arrays of symbols and options for validation errors:
|
|
148
|
+
|
|
149
|
+
```rb
|
|
150
|
+
class ImageUploader < Shrine
|
|
151
|
+
plugin :validation_helpers
|
|
152
|
+
|
|
153
|
+
Attacher.validate do
|
|
154
|
+
validate_max_size 10 * 1024 * 1024, message: -> (max) { [:too_large, max: max] }
|
|
155
|
+
validate_mime_type %w[image/jpeg image/png], message: :not_image
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
```
|
|
159
|
+
```yml
|
|
160
|
+
en:
|
|
161
|
+
activerecord:
|
|
162
|
+
errors:
|
|
163
|
+
models:
|
|
164
|
+
photo:
|
|
165
|
+
attributes:
|
|
166
|
+
image:
|
|
167
|
+
max_size: "must not be larger than %{max_size} bytes"
|
|
168
|
+
not_image: "must be a common image format"
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
#### Skipping Validations
|
|
172
|
+
|
|
85
173
|
If don't want the attachment module to merge file validations errors into
|
|
86
|
-
model errors, you can
|
|
174
|
+
model errors, you can set `:validations` to `false`:
|
|
87
175
|
|
|
88
176
|
```rb
|
|
89
177
|
plugin :activerecord, validations: false
|
|
90
178
|
```
|
|
91
179
|
|
|
92
|
-
|
|
180
|
+
## Attacher
|
|
181
|
+
|
|
182
|
+
You can also use `Shrine::Attacher` directly (with or without the
|
|
183
|
+
`Shrine::Attachment` module):
|
|
184
|
+
|
|
185
|
+
```rb
|
|
186
|
+
class Photo < ActiveRecord::Base # has `image_data` column
|
|
187
|
+
end
|
|
188
|
+
```
|
|
189
|
+
```rb
|
|
190
|
+
photo = Photo.new
|
|
191
|
+
attacher = ImageUploader::Attacher.from_model(photo, :image)
|
|
192
|
+
|
|
193
|
+
attacher.assign(file) # cache
|
|
194
|
+
|
|
195
|
+
attacher.file #=> #<Shrine::UploadedFile id="bc2e13.jpg" storage=:cache ...>
|
|
196
|
+
photo.image_data #=> '{"id":"bc2e13.jpg","storage":"cache","metadata":{...}}'
|
|
197
|
+
|
|
198
|
+
photo.save # persist
|
|
199
|
+
attacher.finalize # promote
|
|
200
|
+
photo.save # persist
|
|
201
|
+
|
|
202
|
+
attacher.file #=> #<Shrine::UploadedFile id="397eca.jpg" storage=:store ...>
|
|
203
|
+
photo.image_data #=> '{"id":"397eca.jpg","storage":"store","metadata":{...}}'
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Persistence
|
|
207
|
+
|
|
208
|
+
The following persistence methods are added to `Shrine::Attacher`:
|
|
209
|
+
|
|
210
|
+
| Method | Description |
|
|
211
|
+
| :----- | :---------- |
|
|
212
|
+
| `Attacher#atomic_promote` | calls `Attacher#promote` and persists if the attachment hasn't changed |
|
|
213
|
+
| `Attacher#atomic_persist` | saves changes if the attachment hasn't changed |
|
|
214
|
+
| `Attacher#persist` | saves any changes to the underlying record |
|
|
215
|
+
|
|
216
|
+
See [persistence] docs for more details.
|
|
217
|
+
|
|
218
|
+
[activerecord]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/activerecord.rb
|
|
219
|
+
[Active Record]: https://guides.rubyonrails.org/active_record_basics.html
|
|
220
|
+
[model]: https://shrinerb.com/docs/plugins/model
|
|
221
|
+
[callbacks]: https://guides.rubyonrails.org/active_record_callbacks.html
|
|
93
222
|
[bug with transaction callbacks]: https://github.com/rails/rails/issues/14493
|
|
223
|
+
[validation]: https://shrinerb.com/docs/plugins/validation
|
|
224
|
+
[persistence]: https://shrinerb.com/docs/plugins/persistence
|
data/doc/plugins/add_metadata.md
CHANGED
|
@@ -1,75 +1,155 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
title: Add Metadata
|
|
3
|
+
---
|
|
2
4
|
|
|
3
|
-
The [`add_metadata`][add_metadata] plugin
|
|
4
|
-
|
|
5
|
+
The [`add_metadata`][add_metadata] plugin allows adding custom metadata to
|
|
6
|
+
uploaded files.
|
|
5
7
|
|
|
6
8
|
```rb
|
|
7
|
-
plugin :add_metadata
|
|
9
|
+
Shrine.plugin :add_metadata
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Metadata block
|
|
13
|
+
|
|
14
|
+
The `Shrine.add_metadata` method allows you to register a block that will get
|
|
15
|
+
executed on upload, where you can return custom metadata:
|
|
16
|
+
|
|
17
|
+
```rb
|
|
18
|
+
require "pdf-reader" # https://github.com/yob/pdf-reader
|
|
8
19
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
{}
|
|
20
|
+
class PdfUploader < Shrine
|
|
21
|
+
add_metadata :page_count do |io|
|
|
22
|
+
reader = PDF::Reader.new(io)
|
|
23
|
+
reader.page_count
|
|
14
24
|
end
|
|
15
25
|
end
|
|
16
26
|
```
|
|
17
27
|
|
|
18
|
-
The above will add
|
|
19
|
-
reader method on Shrine::UploadedFile
|
|
28
|
+
The above will add `page_count` key to the metadata hash, and also create the
|
|
29
|
+
`#page_count` reader method on the `Shrine::UploadedFile`.
|
|
20
30
|
|
|
21
31
|
```rb
|
|
22
|
-
|
|
32
|
+
uploaded_file.metadata["page_count"] #=> 30
|
|
23
33
|
# or
|
|
24
|
-
|
|
34
|
+
uploaded_file.page_count #=> 30
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Skipping nil values
|
|
38
|
+
|
|
39
|
+
By default, if your block returns `nil` then the `nil` value will be stored into
|
|
40
|
+
metadata. If you do not want to store anything when your block returns nil, you
|
|
41
|
+
can use the `skip_nil: true` option:
|
|
42
|
+
|
|
43
|
+
```rb
|
|
44
|
+
class PdfUploader < Shrine
|
|
45
|
+
add_metadata :pages, skip_nil: true do |io|
|
|
46
|
+
if is_pdf?(io)
|
|
47
|
+
reader = PDF::Reader.new(io)
|
|
48
|
+
reader.page_count
|
|
49
|
+
else
|
|
50
|
+
# If this is not a PDF, then the pages metadata will not be stored
|
|
51
|
+
nil
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
25
55
|
```
|
|
26
56
|
|
|
57
|
+
### Multiple values
|
|
58
|
+
|
|
27
59
|
You can also extract multiple metadata values at once, by using `add_metadata`
|
|
28
60
|
without an argument and returning a hash of metadata.
|
|
29
61
|
|
|
30
62
|
```rb
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
63
|
+
require "exif" # https://github.com/tonytonyjan/exif
|
|
64
|
+
|
|
65
|
+
class ImageUploader < Shrine
|
|
66
|
+
add_metadata do |io|
|
|
67
|
+
begin
|
|
68
|
+
data = Exif::Data.new(io)
|
|
69
|
+
rescue Exif::NotReadable # not a valid image
|
|
70
|
+
next {}
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
{ "date_time" => data.date_time,
|
|
74
|
+
"flash" => data.flash,
|
|
75
|
+
"focal_length" => data.focal_length,
|
|
76
|
+
"exposure_time" => data.exposure_time }
|
|
36
77
|
end
|
|
37
|
-
|
|
38
|
-
{ date_time: data.date_time,
|
|
39
|
-
flash: data.flash,
|
|
40
|
-
focal_length: data.focal_length,
|
|
41
|
-
exposure_time: data.exposure_time }
|
|
42
78
|
end
|
|
43
79
|
```
|
|
80
|
+
```rb
|
|
81
|
+
uploaded_file.metadata #=>
|
|
82
|
+
# {
|
|
83
|
+
# ...
|
|
84
|
+
# "date_time" => "2019:07:20 16:16:08",
|
|
85
|
+
# "flash" => 16,
|
|
86
|
+
# "focal_length" => 26/1,
|
|
87
|
+
# "exposure_time" => 1/500,
|
|
88
|
+
# }
|
|
89
|
+
```
|
|
44
90
|
|
|
45
91
|
In this case Shrine won't automatically create reader methods for the extracted
|
|
46
|
-
metadata
|
|
47
|
-
`#metadata_method`.
|
|
92
|
+
metadata, but you can create them via `Shrine.metadata_method`:
|
|
48
93
|
|
|
49
94
|
```rb
|
|
50
|
-
|
|
95
|
+
class ImageUploader < Shrine
|
|
96
|
+
# ...
|
|
97
|
+
metadata_method :date_time, :flash
|
|
98
|
+
end
|
|
51
99
|
```
|
|
100
|
+
```rb
|
|
101
|
+
uploaded_file.date_time #=> "2019:07:20 16:16:08"
|
|
102
|
+
uploaded_file.flash #=> 16
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Ensuring file
|
|
52
106
|
|
|
53
107
|
The `io` might not always be a file object, so if you're using an analyzer
|
|
54
108
|
which requires the source file to be on disk, you can use `Shrine.with_file` to
|
|
55
109
|
ensure you have a file object.
|
|
56
110
|
|
|
57
111
|
```rb
|
|
58
|
-
|
|
59
|
-
|
|
112
|
+
require "streamio-ffmpeg" # https://github.com/streamio/streamio-ffmpeg
|
|
113
|
+
|
|
114
|
+
class VideoUploader < Shrine
|
|
115
|
+
add_metadata do |io|
|
|
116
|
+
movie = Shrine.with_file(io) do |file|
|
|
117
|
+
FFMPEG::Movie.new(file.path)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
{ "duration" => movie.duration,
|
|
121
|
+
"bitrate" => movie.bitrate,
|
|
122
|
+
"resolution" => movie.resolution,
|
|
123
|
+
"frame_rate" => movie.frame_rate }
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Uploader options
|
|
129
|
+
|
|
130
|
+
Uploader options are also yielded to the block, you can access them for more
|
|
131
|
+
context:
|
|
60
132
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
133
|
+
```rb
|
|
134
|
+
add_metadata do |io, **options|
|
|
135
|
+
options #=>
|
|
136
|
+
# {
|
|
137
|
+
# record: #<Photo>,
|
|
138
|
+
# name: :image,
|
|
139
|
+
# action: :store,
|
|
140
|
+
# metadata: { ... },
|
|
141
|
+
# ...
|
|
142
|
+
# }
|
|
65
143
|
end
|
|
66
144
|
```
|
|
67
145
|
|
|
68
|
-
|
|
146
|
+
#### Metadata
|
|
147
|
+
|
|
148
|
+
The `:metadata` option holds metadata that was extracted so far:
|
|
69
149
|
|
|
70
150
|
```rb
|
|
71
|
-
add_metadata :foo do |io,
|
|
72
|
-
|
|
151
|
+
add_metadata :foo do |io, metadata:, **|
|
|
152
|
+
metadata #=>
|
|
73
153
|
# {
|
|
74
154
|
# "size" => 239823,
|
|
75
155
|
# "filename" => "nature.jpg",
|
|
@@ -79,8 +159,8 @@ add_metadata :foo do |io, context|
|
|
|
79
159
|
"foo"
|
|
80
160
|
end
|
|
81
161
|
|
|
82
|
-
add_metadata :bar do |io,
|
|
83
|
-
|
|
162
|
+
add_metadata :bar do |io, metadata:, **|
|
|
163
|
+
metadata #=>
|
|
84
164
|
# {
|
|
85
165
|
# "size" => 239823,
|
|
86
166
|
# "filename" => "nature.jpg",
|
|
@@ -92,4 +172,25 @@ add_metadata :bar do |io, context|
|
|
|
92
172
|
end
|
|
93
173
|
```
|
|
94
174
|
|
|
95
|
-
|
|
175
|
+
## Updating metadata
|
|
176
|
+
|
|
177
|
+
If you just wish to add some custom metadata to existing uploads, you can do it
|
|
178
|
+
with `UploadedFile#add_metadata` (and write the changes back to the model):
|
|
179
|
+
|
|
180
|
+
```rb
|
|
181
|
+
attacher.file.add_metadata("foo" => "bar")
|
|
182
|
+
attacher.write # write changes to the model attribute
|
|
183
|
+
|
|
184
|
+
attacher.file.metadata #=> { ..., "foo" => "bar" }
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
You can also use the `Attacher#add_metadata` shorthand, which also takes care
|
|
188
|
+
of syncing the model:
|
|
189
|
+
|
|
190
|
+
```rb
|
|
191
|
+
attacher.add_metadata("foo" => "bar")
|
|
192
|
+
|
|
193
|
+
attacher.file.metadata #=> { ..., "foo" => "bar" }
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
[add_metadata]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/add_metadata.rb
|