shrine 3.0.0.alpha → 3.0.0.beta
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of shrine might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +34 -2
- data/README.md +1 -1
- data/doc/creating_persistence_plugins.md +20 -63
- data/doc/plugins/activerecord.md +13 -106
- data/doc/plugins/add_metadata.md +31 -9
- data/doc/plugins/atomic_helpers.md +33 -9
- data/doc/plugins/cached_attachment_data.md +3 -3
- data/doc/plugins/data_uri.md +16 -19
- data/doc/plugins/default_storage.md +32 -8
- data/doc/plugins/default_url.md +21 -9
- data/doc/plugins/derivation_endpoint.md +48 -0
- data/doc/plugins/derivatives.md +74 -63
- data/doc/plugins/entity.md +27 -2
- data/doc/plugins/included.md +8 -7
- data/doc/plugins/metadata_attributes.md +20 -5
- data/doc/plugins/model.md +22 -2
- data/doc/plugins/persistence.md +89 -0
- data/doc/plugins/remote_url.md +41 -45
- data/doc/plugins/remove_attachment.md +23 -4
- data/doc/plugins/remove_invalid.md +3 -4
- data/doc/plugins/restore_cached_data.md +3 -1
- data/doc/plugins/sequel.md +13 -105
- data/doc/plugins/signature.md +3 -3
- data/lib/shrine/attachment.rb +11 -1
- data/lib/shrine/plugins/_persistence.rb +69 -0
- data/lib/shrine/plugins/activerecord.rb +31 -81
- data/lib/shrine/plugins/atomic_helpers.rb +13 -3
- data/lib/shrine/plugins/backgrounding.rb +8 -8
- data/lib/shrine/plugins/cached_attachment_data.rb +2 -6
- data/lib/shrine/plugins/data_uri.rb +2 -6
- data/lib/shrine/plugins/default_storage.rb +28 -2
- data/lib/shrine/plugins/derivation_endpoint.rb +3 -9
- data/lib/shrine/plugins/derivatives.rb +26 -17
- data/lib/shrine/plugins/entity.rb +24 -16
- data/lib/shrine/plugins/included.rb +1 -0
- data/lib/shrine/plugins/infer_extension.rb +2 -0
- data/lib/shrine/plugins/metadata_attributes.rb +18 -8
- data/lib/shrine/plugins/model.rb +35 -14
- data/lib/shrine/plugins/remote_url.rb +2 -6
- data/lib/shrine/plugins/remove_attachment.rb +2 -6
- data/lib/shrine/plugins/remove_invalid.rb +10 -6
- data/lib/shrine/plugins/sequel.rb +31 -78
- data/lib/shrine/plugins/upload_options.rb +2 -2
- data/lib/shrine/plugins/validation.rb +1 -11
- data/lib/shrine/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c5f2d3f6519d99e728cdfffe80783d0278f171bb6f8a850b4840d2d9fb92eda5
|
4
|
+
data.tar.gz: 28566d4950a3ad23cb657e699db8a0861283efb8709a7a70d6a20c83d8a5c0c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0cc989a0037051dd2cc84785a7a0a6080667e450ae8f1e95c4204d4474f9fac98d97498f435c82aed20036963ca86425ccf31e3d07ea274e9113e3b79439bb16
|
7
|
+
data.tar.gz: 6f4e12336f30753d55b53337efd695a712c4971744bd012497f79418890b3ed910084e6af7fe57c5c05025f854f44ffbb969e5c0aa3cba4aa0d9b729d1225267
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,37 @@
|
|
1
|
+
## 3.0.0.beta (2019-08-29)
|
2
|
+
|
3
|
+
* `atomic_helpers` – Rename `:data` argument to `:file` in `Attacher.retrieve` (@janko)
|
4
|
+
|
5
|
+
* `atomic_helpers` – Add `Attacher#file_data` which returns only main file data without metadata (@janko)
|
6
|
+
|
7
|
+
* `model` – Add `Attacher#set_model` for setting model without loading attachment (@janko)
|
8
|
+
|
9
|
+
* `entity` – Add `Attacher#set_entity` for setting entity without loading attachment (@janko)
|
10
|
+
|
11
|
+
* `core` – Define `#<name>_attacher` class method when including `Shrine::Attachment` (@janko)
|
12
|
+
|
13
|
+
* `derivation_endpoint` – Send only `:derivation` in the instrumentation event payload (@janko)
|
14
|
+
|
15
|
+
* `default_storage` – Add `Attacher.default_cache` and `Attacher.default_store` for settings (@janko)
|
16
|
+
|
17
|
+
* `default_storage` – Deprecate `record` & `name` arguments to storage block (@janko)
|
18
|
+
|
19
|
+
* `default_storage` – Evaluate storage block in context of `Attacher` instance (@janko)
|
20
|
+
|
21
|
+
* Simplify persistence interface (@janko)
|
22
|
+
|
23
|
+
* `upload_options` – Keep `Shrine#_upload` private (@janko)
|
24
|
+
|
25
|
+
* `infer_extension` – Keep `Shrine#basic_location` private (@janko)
|
26
|
+
|
27
|
+
* `model` – Add `#<name>_changed?` method to attachment module (@janko)
|
28
|
+
|
29
|
+
* `core` – Make it easier for plugins to define entity and model attachment methods (@janko)
|
30
|
+
|
31
|
+
* `derivatives` – Add `#<name>_derivatives!` module method which delegates to `#create_derivatives` (@janko)
|
32
|
+
|
33
|
+
* `derivatives` – Change `#create_derivatives` to forward all arguments to `#process_derivatives` (@janko)
|
34
|
+
|
1
35
|
## 3.0.0.alpha (2019-08-19)
|
2
36
|
|
3
37
|
* `form_assign` – Add new plugin for assigning attachment from form params without a form object (@janko)
|
@@ -96,8 +130,6 @@
|
|
96
130
|
|
97
131
|
* `attacher_options` – Add new plugin for setting default attacher operation options (@janko)
|
98
132
|
|
99
|
-
* `validation` – Add `Attacher#validate_options` for registering default validation options (@janko)
|
100
|
-
|
101
133
|
* `validation` – Allow skipping validations on attaching by passing `validate: false` (@janko)
|
102
134
|
|
103
135
|
* `validation` – Add `:validate` option to `Attacher#assign` or `Attacher#attach` for passing options to validation block (@janko)
|
data/README.md
CHANGED
@@ -71,96 +71,53 @@ end
|
|
71
71
|
|
72
72
|
## Attacher
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
It's recommended to implement an `Attacher#persist` method which persists
|
77
|
-
the attached file to the record.
|
78
|
-
|
79
|
-
```rb
|
80
|
-
module Shrine::Plugins::Raptor
|
81
|
-
# ...
|
82
|
-
module AttacherMethods
|
83
|
-
# ...
|
84
|
-
def persist(...)
|
85
|
-
# persist attachment data
|
86
|
-
end
|
87
|
-
# ...
|
88
|
-
end
|
89
|
-
# ...
|
90
|
-
end
|
91
|
-
```
|
92
|
-
|
93
|
-
This way other 3rd-party plugins can use `Attacher#persist` and know it will do
|
94
|
-
the right thing regardless of which persistence plugin is used.
|
95
|
-
|
96
|
-
### Atomic promotion & persistence
|
97
|
-
|
98
|
-
When using [`backgrounding`][backgrounding] plugin, it's useful to be able to
|
99
|
-
make promotion/persistence atomic. The [`atomic_helpers`][atomic_helpers]
|
100
|
-
plugin provides the abstract interface, and in your persistence plugin you can
|
101
|
-
provide wrappers.
|
74
|
+
To help define persistence methods on the `Attacher` according to the
|
75
|
+
convention, load the `_persistence` plugin as a dependency:
|
102
76
|
|
103
77
|
```rb
|
104
78
|
module Shrine::Plugins::Raptor
|
105
79
|
def self.load_dependencies(uploader, **)
|
106
80
|
# ...
|
107
|
-
uploader.plugin :
|
108
|
-
end
|
109
|
-
# ...
|
110
|
-
module AttacherMethods
|
111
|
-
# ...
|
112
|
-
def atomic_promote(...)
|
113
|
-
# call #abstract_atomic_promote from atomic_helpers plugin
|
114
|
-
end
|
115
|
-
|
116
|
-
def atomic_persist(...)
|
117
|
-
# call #abstract_atomic_persist from atomic_helpers plugin
|
118
|
-
end
|
119
|
-
# ...
|
81
|
+
uploader.plugin :_persistence, plugin: self
|
120
82
|
end
|
121
83
|
# ...
|
122
84
|
end
|
123
85
|
```
|
124
86
|
|
125
|
-
|
126
|
-
how this integration should look like.
|
87
|
+
This will define the following attacher methods:
|
127
88
|
|
128
|
-
|
89
|
+
* `Attacher#persist`
|
90
|
+
* `Attacher#atomic_persist`
|
91
|
+
* `Attacher#atomic_promote`
|
129
92
|
|
130
|
-
|
131
|
-
|
93
|
+
For those methods to work, we'll need to implement the following methods:
|
94
|
+
|
95
|
+
* `Attacher#<library>_persist`
|
96
|
+
* `Attacher#<library>_reload`
|
97
|
+
* `Attacher#<library>?`
|
132
98
|
|
133
99
|
```rb
|
134
100
|
module Shrine::Plugins::Raptor
|
135
101
|
# ...
|
136
102
|
module AttacherMethods
|
137
103
|
# ...
|
138
|
-
|
139
|
-
|
104
|
+
private
|
105
|
+
|
106
|
+
def raptor_persist
|
107
|
+
# persist attached file to the record
|
140
108
|
end
|
141
|
-
alias atomic_promote raptor_atomic_promote
|
142
109
|
|
143
|
-
def
|
144
|
-
#
|
110
|
+
def raptor_reload
|
111
|
+
# yield reloaded record (see atomic_helpers plugin)
|
145
112
|
end
|
146
|
-
alias atomic_persist raptor_atomic_persist
|
147
113
|
|
148
|
-
def
|
149
|
-
#
|
114
|
+
def raptor?
|
115
|
+
# returns whether current model/entity belongs to Raptor
|
150
116
|
end
|
151
|
-
alias persist raptor_persist
|
152
|
-
# ...
|
153
117
|
end
|
154
|
-
# ...
|
155
118
|
end
|
156
119
|
```
|
157
120
|
|
158
|
-
That way the user can always specify from which persistence plugin they're
|
159
|
-
calling a certain method, even when multiple persistence plugins are loaded
|
160
|
-
simultaneously. The latter can be the case if the user is using multiple
|
161
|
-
database libraries in a single application, or if they're transitioning from
|
162
|
-
one library to another.
|
163
|
-
|
164
121
|
[Writing a Plugin]: /doc/creating_plugins.md#readme
|
165
122
|
[Active Record pattern]: https://www.martinfowler.com/eaaCatalog/activeRecord.html
|
166
123
|
[model]: /doc/plugins/model.md#readme
|
data/doc/plugins/activerecord.md
CHANGED
@@ -21,7 +21,7 @@ end
|
|
21
21
|
|
22
22
|
### Callbacks
|
23
23
|
|
24
|
-
#### Save
|
24
|
+
#### After Save
|
25
25
|
|
26
26
|
After a record is saved and the transaction is committed, `Attacher#finalize`
|
27
27
|
is called, which promotes cached file to permanent storage and deletes previous
|
@@ -37,7 +37,7 @@ photo.save
|
|
37
37
|
photo.image.storage_key #=> :store
|
38
38
|
```
|
39
39
|
|
40
|
-
#### Destroy
|
40
|
+
#### After Destroy
|
41
41
|
|
42
42
|
After a record is destroyed and the transaction is committed,
|
43
43
|
`Attacher#destroy_attached` method is called, which deletes stored attached
|
@@ -67,7 +67,7 @@ Active Record also currently has a [bug with transaction callbacks], so if
|
|
67
67
|
you have any "after commit" callbacks, make sure to include Shrine's attachment
|
68
68
|
module *after* they have all been defined.
|
69
69
|
|
70
|
-
#### Skipping
|
70
|
+
#### Skipping Callbacks
|
71
71
|
|
72
72
|
If you don't want the attachment module to add any callbacks to your Active
|
73
73
|
Record model, you can set `:callbacks` to `false`:
|
@@ -97,7 +97,7 @@ photo.valid?
|
|
97
97
|
photo.errors #=> { image: ["size must not be greater than 10.0 MB"] }
|
98
98
|
```
|
99
99
|
|
100
|
-
#### Presence
|
100
|
+
#### Attachment Presence
|
101
101
|
|
102
102
|
If you want to validate presence of the attachment, you can use Active Record's
|
103
103
|
presence validator:
|
@@ -136,7 +136,7 @@ en:
|
|
136
136
|
not_image: "must be a common image format"
|
137
137
|
```
|
138
138
|
|
139
|
-
#### Skipping
|
139
|
+
#### Skipping Validations
|
140
140
|
|
141
141
|
If don't want the attachment module to merge file validations errors into
|
142
142
|
model errors, you can set `:validations` to `false`:
|
@@ -150,107 +150,15 @@ plugin :activerecord, validations: false
|
|
150
150
|
This section will cover methods added to the `Shrine::Attacher` instance. If
|
151
151
|
you're not familar with how to obtain it, see the [`model`][model] plugin docs.
|
152
152
|
|
153
|
-
|
153
|
+
The following persistence methods are added to the attacher:
|
154
154
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
`Attacher#
|
155
|
+
| Method | Description |
|
156
|
+
| :----- | :---------- |
|
157
|
+
| `Attacher#atomic_promote` | calls `Attacher#promote` and persists if the attachment hasn't changed |
|
158
|
+
| `Attacher#atomic_persist` | saves changes if the attachment hasn't changed |
|
159
|
+
| `Attacher#persist` | saves any changes to the underlying record |
|
159
160
|
|
160
|
-
|
161
|
-
# in your controller
|
162
|
-
attacher.attach_cached(io)
|
163
|
-
attacher.cached? #=> true
|
164
|
-
```
|
165
|
-
```rb
|
166
|
-
# in a background job
|
167
|
-
attacher.atomic_promote # promotes cached file and persists
|
168
|
-
attacher.stored? #=> true
|
169
|
-
```
|
170
|
-
|
171
|
-
After cached file is uploaded to permanent storage, the record is reloaded in
|
172
|
-
order to check whether the attachment hasn't changed, and if it hasn't the
|
173
|
-
attachment is persisted. If the attachment has changed,
|
174
|
-
`Shrine::AttachmentChanged` exception is raised.
|
175
|
-
|
176
|
-
Additional options are passed to `Attacher#promote`.
|
177
|
-
|
178
|
-
#### Reloader & persister
|
179
|
-
|
180
|
-
You can change how the record is reloaded or persisted during atomic promotion:
|
181
|
-
|
182
|
-
```rb
|
183
|
-
# reloader
|
184
|
-
attacher.atomic_promote(reload: :lock) # uses database locking (default)
|
185
|
-
attacher.atomic_promote(reload: :fetch) # reloads with no locking
|
186
|
-
attacher.atomic_promote(reload: ->(&b){...}) # custom reloader (see atomic_helpers plugin docs)
|
187
|
-
attacher.atomic_promote(reload: false) # skips reloading
|
188
|
-
|
189
|
-
# persister
|
190
|
-
attacher.atomic_promote(persist: :save) # persists stored file (default)
|
191
|
-
attacher.atomic_promote(persist: ->{...}) # custom persister (see atomic_helpers plugin docs)
|
192
|
-
attacher.atomic_promote(persist: false) # skips persistence
|
193
|
-
```
|
194
|
-
|
195
|
-
For more details, see the [`atomic_helpers`][atomic_helpers] plugin docs.
|
196
|
-
|
197
|
-
### Atomic persistence
|
198
|
-
|
199
|
-
If you're updating something based on the attached file
|
200
|
-
[asynchronously][backgrounding], you might want to handle the possibility of
|
201
|
-
the attachment changing in the meanwhile. You can do that with
|
202
|
-
`Attacher#atomic_persist`:
|
203
|
-
|
204
|
-
```rb
|
205
|
-
# in a background job
|
206
|
-
attacher.refresh_metadata! # refresh_metadata plugin
|
207
|
-
attacher.atomic_persist # persists attachment data
|
208
|
-
```
|
209
|
-
|
210
|
-
The record is first reloaded in order to check whether the attachment hasn't
|
211
|
-
changed, and if it hasn't the attachment is persisted. If the attachment has
|
212
|
-
changed, `Shrine::AttachmentChanged` exception is raised.
|
213
|
-
|
214
|
-
#### Reloader & persister
|
215
|
-
|
216
|
-
You can change how the record is reloaded or persisted during atomic
|
217
|
-
persistence:
|
218
|
-
|
219
|
-
```rb
|
220
|
-
# reloader
|
221
|
-
attacher.atomic_persist(reload: :lock) # uses database locking (default)
|
222
|
-
attacher.atomic_persist(reload: :fetch) # reloads with no locking
|
223
|
-
attacher.atomic_persist(reload: ->(&b){}) # custom reloader (see atomic_helpers plugin docs)
|
224
|
-
attacher.atomic_persist(reload: false) # skips reloading
|
225
|
-
|
226
|
-
# persister
|
227
|
-
attacher.atomic_persist(persist: :save) # persists stored file (default)
|
228
|
-
attacher.atomic_persist(persist: ->{}) # custom persister (see atomic_helpers plugin docs)
|
229
|
-
attacher.atomic_persist(persist: false) # skips persistence
|
230
|
-
```
|
231
|
-
|
232
|
-
For more details, see the [`atomic_helpers`][atomic_helpers] plugin docs.
|
233
|
-
|
234
|
-
### Persistence
|
235
|
-
|
236
|
-
You can call `Attacher#persist` to save any changes to the underlying record:
|
237
|
-
|
238
|
-
```rb
|
239
|
-
attacher.attach(io)
|
240
|
-
attacher.persist # saves the underlying record
|
241
|
-
```
|
242
|
-
|
243
|
-
### With other database plugins
|
244
|
-
|
245
|
-
If you have another database plugin loaded together with the `activerecord`
|
246
|
-
plugin, you can prefix any method above with `activerecord_*` to avoid naming
|
247
|
-
clashes:
|
248
|
-
|
249
|
-
```rb
|
250
|
-
attacher.activerecord_atomic_promote
|
251
|
-
attacher.activerecord_atomic_persist
|
252
|
-
attacher.activerecord_persist
|
253
|
-
```
|
161
|
+
See [persistence] docs for more details.
|
254
162
|
|
255
163
|
[activerecord]: /lib/shrine/plugins/activerecord.rb
|
256
164
|
[Active Record]: https://guides.rubyonrails.org/active_record_basics.html
|
@@ -258,5 +166,4 @@ attacher.activerecord_persist
|
|
258
166
|
[callbacks]: https://guides.rubyonrails.org/active_record_callbacks.html
|
259
167
|
[bug with transaction callbacks]: https://github.com/rails/rails/issues/14493
|
260
168
|
[validation]: /doc/plugins/validation.md#readme
|
261
|
-
[
|
262
|
-
[backgrounding]: /doc/plugins/backgrounding.md#readme
|
169
|
+
[persistence]: /doc/plugins/persistence.md#readme
|
data/doc/plugins/add_metadata.md
CHANGED
@@ -6,7 +6,7 @@ extracting and adding custom metadata values.
|
|
6
6
|
```rb
|
7
7
|
plugin :add_metadata
|
8
8
|
|
9
|
-
add_metadata :exif do |io
|
9
|
+
add_metadata :exif do |io|
|
10
10
|
begin
|
11
11
|
Exif::Data.new(io).to_h
|
12
12
|
rescue Exif::NotReadable # not a valid image
|
@@ -16,7 +16,7 @@ end
|
|
16
16
|
```
|
17
17
|
|
18
18
|
The above will add "exif" to the metadata hash, and also create the `#exif`
|
19
|
-
reader method on Shrine::UploadedFile
|
19
|
+
reader method on `Shrine::UploadedFile`.
|
20
20
|
|
21
21
|
```rb
|
22
22
|
image.metadata["exif"]
|
@@ -24,11 +24,13 @@ image.metadata["exif"]
|
|
24
24
|
image.exif
|
25
25
|
```
|
26
26
|
|
27
|
+
## Multiple values
|
28
|
+
|
27
29
|
You can also extract multiple metadata values at once, by using `add_metadata`
|
28
30
|
without an argument and returning a hash of metadata.
|
29
31
|
|
30
32
|
```rb
|
31
|
-
add_metadata do |io
|
33
|
+
add_metadata do |io|
|
32
34
|
begin
|
33
35
|
data = Exif::Data.new(io)
|
34
36
|
rescue Exif::NotReadable # not a valid image
|
@@ -50,12 +52,14 @@ metadata on Shrine::UploadedFile, but you can create them via
|
|
50
52
|
metadata_method :date_time, :flash
|
51
53
|
```
|
52
54
|
|
55
|
+
## Ensuring file
|
56
|
+
|
53
57
|
The `io` might not always be a file object, so if you're using an analyzer
|
54
58
|
which requires the source file to be on disk, you can use `Shrine.with_file` to
|
55
59
|
ensure you have a file object.
|
56
60
|
|
57
61
|
```rb
|
58
|
-
add_metadata do |io
|
62
|
+
add_metadata do |io|
|
59
63
|
movie = Shrine.with_file(io) { |file| FFMPEG::Movie.new(file.path) }
|
60
64
|
|
61
65
|
{ "duration" => movie.duration,
|
@@ -65,11 +69,29 @@ add_metadata do |io, context|
|
|
65
69
|
end
|
66
70
|
```
|
67
71
|
|
68
|
-
|
72
|
+
## Uploader options
|
73
|
+
|
74
|
+
Uploader options are also yielded to the block, you can access them for more
|
75
|
+
context:
|
76
|
+
|
77
|
+
```rb
|
78
|
+
add_metadata do |io, **options|
|
79
|
+
options #=>
|
80
|
+
# {
|
81
|
+
# record: #<Photo>,
|
82
|
+
# name: :image,
|
83
|
+
# action: :store,
|
84
|
+
# metadata: { ... },
|
85
|
+
# ...
|
86
|
+
# }
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
The `:metadata` option holds metadata that was extracted so far:
|
69
91
|
|
70
92
|
```rb
|
71
|
-
add_metadata :foo do |io,
|
72
|
-
|
93
|
+
add_metadata :foo do |io, metadata:, **|
|
94
|
+
metadata #=>
|
73
95
|
# {
|
74
96
|
# "size" => 239823,
|
75
97
|
# "filename" => "nature.jpg",
|
@@ -79,8 +101,8 @@ add_metadata :foo do |io, context|
|
|
79
101
|
"foo"
|
80
102
|
end
|
81
103
|
|
82
|
-
add_metadata :bar do |io,
|
83
|
-
|
104
|
+
add_metadata :bar do |io, metadata:, **|
|
105
|
+
metadata #=>
|
84
106
|
# {
|
85
107
|
# "size" => 239823,
|
86
108
|
# "filename" => "nature.jpg",
|
@@ -18,9 +18,9 @@ given attachment data matches the attached file on the record.
|
|
18
18
|
```rb
|
19
19
|
# with a model instance
|
20
20
|
Shrine::Attacher.retrieve(
|
21
|
-
model:
|
22
|
-
name:
|
23
|
-
|
21
|
+
model: photo,
|
22
|
+
name: :image,
|
23
|
+
file: { "id" => "abc123", "storage" => "cache" },
|
24
24
|
)
|
25
25
|
#=> #<Shrine::Attacher ...>
|
26
26
|
|
@@ -28,7 +28,7 @@ Shrine::Attacher.retrieve(
|
|
28
28
|
Shrine::Attacher.retrieve(
|
29
29
|
entity: photo,
|
30
30
|
name: :image,
|
31
|
-
|
31
|
+
file: { "id" => "abc123", "storage" => "cache" },
|
32
32
|
)
|
33
33
|
#=> #<Shrine::Attacher ...>
|
34
34
|
```
|
@@ -42,7 +42,7 @@ class Photo
|
|
42
42
|
end
|
43
43
|
```
|
44
44
|
```rb
|
45
|
-
Shrine::Attacher.retrieve(model: photo, name: :image,
|
45
|
+
Shrine::Attacher.retrieve(model: photo, name: :image, file: { ... })
|
46
46
|
#=> #<ImageUploader::Attacher ...>
|
47
47
|
```
|
48
48
|
|
@@ -51,7 +51,7 @@ Otherwise it will call `Attacher.from_model`/`Attacher.from_entity` from the
|
|
51
51
|
`Attacher.retrieve` on the appropriate attacher class.
|
52
52
|
|
53
53
|
```rb
|
54
|
-
ImageUploader::Attacher.retrieve(entity: photo, name: :image,
|
54
|
+
ImageUploader::Attacher.retrieve(entity: photo, name: :image, file: { ... })
|
55
55
|
#=> #<ImageUploader::Attacher ...>
|
56
56
|
```
|
57
57
|
|
@@ -60,16 +60,30 @@ a `Shrine::AttachmentChanged` exception is raised. Note that metadata is
|
|
60
60
|
allowed to differ, Shrine will only compare location and storage of the file.
|
61
61
|
|
62
62
|
```rb
|
63
|
-
photo.image_data #=> '{"id":"foo","storage":"
|
63
|
+
photo.image_data #=> '{"id":"foo","storage":"store","metadata":{...}}'
|
64
64
|
|
65
65
|
Shrine::Attacher.retrieve(
|
66
66
|
model: photo,
|
67
67
|
name: :image,
|
68
|
-
|
68
|
+
file: { "id" => "bar", "storage" => "store" },
|
69
69
|
)
|
70
70
|
# ~> Shrine::AttachmentChanged: attachment has changed
|
71
71
|
```
|
72
72
|
|
73
|
+
### File data
|
74
|
+
|
75
|
+
The `Attacher#file_data` method can be used for sending the attached file data
|
76
|
+
into a background job. It returns only location and storage of the attached
|
77
|
+
file, leaving out any metadata or derivatives data that `Attacher#data` would
|
78
|
+
return. This way the background job payload is kept light.
|
79
|
+
|
80
|
+
```rb
|
81
|
+
attacher.file_data #=> { "id" => "abc123", "storage" => "store" }
|
82
|
+
```
|
83
|
+
|
84
|
+
This value can then be passed as the `:file` argument to
|
85
|
+
`Shrine::Attacher.retrieve`.
|
86
|
+
|
73
87
|
## Promoting
|
74
88
|
|
75
89
|
The `Attacher#abstract_atomic_promote` method provided by the plugin promotes
|
@@ -94,6 +108,15 @@ attacher.stored? #=> true
|
|
94
108
|
If the attachment has changed during promotion, the promoted file is deleted and
|
95
109
|
a `Shrine::AttachmentChanged` exception is raised.
|
96
110
|
|
111
|
+
If you want to execute some code after the attachment change check but before
|
112
|
+
persistence, you can pass a block:
|
113
|
+
|
114
|
+
```rb
|
115
|
+
attacher.abstract_atomic_promote(**options) do |reloaded_attacher|
|
116
|
+
# this will be executed before persistence
|
117
|
+
end
|
118
|
+
```
|
119
|
+
|
97
120
|
Any additional options to `Attacher#abstract_atomic_promote` are forwarded to
|
98
121
|
`Attacher#promote`.
|
99
122
|
|
@@ -142,7 +165,8 @@ attacher.set(new_file)
|
|
142
165
|
attacher.abstract_atomic_persist(original_file, **options)
|
143
166
|
```
|
144
167
|
|
145
|
-
If you want to execute some code
|
168
|
+
If you want to execute some code after the attachment change check but before
|
169
|
+
persistence, you can pass a block:
|
146
170
|
|
147
171
|
```rb
|
148
172
|
attacher.abstract_atomic_persist(**options) do |reloaded_attacher|
|
@@ -13,13 +13,13 @@ cached file as JSON, and should be used to set the value of the hidden form
|
|
13
13
|
field.
|
14
14
|
|
15
15
|
```rb
|
16
|
-
|
16
|
+
photo.cached_image_data #=> '{"id":"38k25.jpg","storage":"cache","metadata":{...}}'
|
17
17
|
```
|
18
18
|
|
19
|
-
This method delegates to `Attacher#
|
19
|
+
This method delegates to `Attacher#cached_data`:
|
20
20
|
|
21
21
|
```rb
|
22
|
-
attacher.
|
22
|
+
attacher.cached_data #=> '{"id":"38k25.jpg","storage":"cache","metadata":{...}}'
|
23
23
|
```
|
24
24
|
|
25
25
|
[cached_attachment_data]: /lib/shrine/plugins/cached_attachment_data.rb
|
data/doc/plugins/data_uri.md
CHANGED
@@ -7,23 +7,22 @@ This plugin is useful for example when using [HTML5 Canvas].
|
|
7
7
|
plugin :data_uri
|
8
8
|
```
|
9
9
|
|
10
|
-
|
11
|
-
and
|
10
|
+
The plugin will add the `#<name>_data_uri` writer to your model, which parses
|
11
|
+
the given data URI string and uploads it to temporary storage:
|
12
12
|
|
13
13
|
```rb
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
user.avatar.mime_type #=> "image/png"
|
19
|
-
user.avatar.size #=> 43423
|
14
|
+
photo.image_data_uri = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA"
|
15
|
+
photo.image.mime_type #=> "image/png"
|
16
|
+
photo.image.size #=> 43423
|
20
17
|
```
|
21
18
|
|
22
|
-
|
23
|
-
`
|
19
|
+
If you're using `Shrine::Attacher` directly, you can use
|
20
|
+
`Attacher#assign_data_uri`:
|
24
21
|
|
25
22
|
```rb
|
26
|
-
attacher.
|
23
|
+
attacher.assign_data_uri("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA")
|
24
|
+
attacher.file.mime_type #=> "image/png"
|
25
|
+
attacher.file.size #=> 43423
|
27
26
|
```
|
28
27
|
|
29
28
|
## Errors
|
@@ -36,13 +35,13 @@ plugin :data_uri, error_message: "data URI was invalid"
|
|
36
35
|
plugin :data_uri, error_message: ->(uri) { I18n.t("errors.data_uri_invalid") }
|
37
36
|
```
|
38
37
|
|
39
|
-
##
|
38
|
+
## Uploader options
|
40
39
|
|
41
|
-
|
42
|
-
|
40
|
+
Any options passed to `Attacher#assign_data_uri` will be forwarded to
|
41
|
+
`Attacher#assign` (and `Shrine#upload`):
|
43
42
|
|
44
43
|
```rb
|
45
|
-
attacher.assign_data_uri(uri, metadata: { "
|
44
|
+
attacher.assign_data_uri(uri, metadata: { "filename" => "nature.jpg" })
|
46
45
|
```
|
47
46
|
|
48
47
|
## File extension
|
@@ -56,9 +55,7 @@ load the `infer_extension` plugin to infer it from the MIME type.
|
|
56
55
|
plugin :infer_extension
|
57
56
|
```
|
58
57
|
|
59
|
-
##
|
60
|
-
|
61
|
-
### `Shrine.data_uri`
|
58
|
+
## Parsing data URI
|
62
59
|
|
63
60
|
If you just want to parse the data URI and create an IO object from it, you can
|
64
61
|
do that with `Shrine.data_uri`. If the data URI cannot be parsed, a
|
@@ -90,7 +87,7 @@ io = Shrine.data_uri("data:,content", filename: "foo.txt")
|
|
90
87
|
io.original_filename #=> "foo.txt"
|
91
88
|
```
|
92
89
|
|
93
|
-
###
|
90
|
+
### Generating data URI
|
94
91
|
|
95
92
|
This plugin also adds `UploadedFile#data_uri` method, which returns a
|
96
93
|
base64-encoded data URI of the file content, and `UploadedFile#base64`, which
|
@@ -1,19 +1,43 @@
|
|
1
1
|
# Default Storage
|
2
2
|
|
3
|
-
The [`default_storage`][default_storage] plugin
|
4
|
-
|
5
|
-
`:cache` and `:store`).
|
3
|
+
The [`default_storage`][default_storage] plugin allows you to change the
|
4
|
+
default temporary and permanent storage a `Shrine::Attacher` object will use
|
5
|
+
(the default is `:cache` and `:store`).
|
6
6
|
|
7
7
|
```rb
|
8
|
-
plugin :default_storage, cache: :
|
8
|
+
plugin :default_storage, cache: :other_cache, store: :other_store
|
9
9
|
```
|
10
10
|
|
11
|
-
|
12
|
-
and
|
13
|
-
`dynamic_storage` plugin. Example:
|
11
|
+
If you want the storage to be dynamic based on `Attacher` data, you can use a
|
12
|
+
block, and it will be evaluated in context of the `Attacher` instance:
|
14
13
|
|
15
14
|
```rb
|
16
|
-
plugin :default_storage, store: ->
|
15
|
+
plugin :default_storage, store: -> {
|
16
|
+
if record.is_a?(Photo)
|
17
|
+
:photo_store
|
18
|
+
else
|
19
|
+
:store
|
20
|
+
end
|
21
|
+
}
|
17
22
|
```
|
18
23
|
|
24
|
+
You can also set default storage with `Attacher#default_cache` and
|
25
|
+
`Attacher#default_store`:
|
26
|
+
|
27
|
+
```rb
|
28
|
+
# default temporary storage
|
29
|
+
Attacher.default_cache :other_cache
|
30
|
+
# or
|
31
|
+
Attacher.default_cache { :other_cache }
|
32
|
+
|
33
|
+
# default permanent storage
|
34
|
+
Attacher.default_store :other_store
|
35
|
+
# or
|
36
|
+
Attacher.default_store { :other_store }
|
37
|
+
```
|
38
|
+
|
39
|
+
The dynamic block is useful in combination with the
|
40
|
+
[`dynamic_storage`][dynamic_storage] plugin.
|
41
|
+
|
19
42
|
[default_storage]: /lib/shrine/plugins/default_storage.rb
|
43
|
+
[dynamic_storage]: /doc/plugins/dynamic_storage.md#readme
|