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.

Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -2
  3. data/README.md +1 -1
  4. data/doc/creating_persistence_plugins.md +20 -63
  5. data/doc/plugins/activerecord.md +13 -106
  6. data/doc/plugins/add_metadata.md +31 -9
  7. data/doc/plugins/atomic_helpers.md +33 -9
  8. data/doc/plugins/cached_attachment_data.md +3 -3
  9. data/doc/plugins/data_uri.md +16 -19
  10. data/doc/plugins/default_storage.md +32 -8
  11. data/doc/plugins/default_url.md +21 -9
  12. data/doc/plugins/derivation_endpoint.md +48 -0
  13. data/doc/plugins/derivatives.md +74 -63
  14. data/doc/plugins/entity.md +27 -2
  15. data/doc/plugins/included.md +8 -7
  16. data/doc/plugins/metadata_attributes.md +20 -5
  17. data/doc/plugins/model.md +22 -2
  18. data/doc/plugins/persistence.md +89 -0
  19. data/doc/plugins/remote_url.md +41 -45
  20. data/doc/plugins/remove_attachment.md +23 -4
  21. data/doc/plugins/remove_invalid.md +3 -4
  22. data/doc/plugins/restore_cached_data.md +3 -1
  23. data/doc/plugins/sequel.md +13 -105
  24. data/doc/plugins/signature.md +3 -3
  25. data/lib/shrine/attachment.rb +11 -1
  26. data/lib/shrine/plugins/_persistence.rb +69 -0
  27. data/lib/shrine/plugins/activerecord.rb +31 -81
  28. data/lib/shrine/plugins/atomic_helpers.rb +13 -3
  29. data/lib/shrine/plugins/backgrounding.rb +8 -8
  30. data/lib/shrine/plugins/cached_attachment_data.rb +2 -6
  31. data/lib/shrine/plugins/data_uri.rb +2 -6
  32. data/lib/shrine/plugins/default_storage.rb +28 -2
  33. data/lib/shrine/plugins/derivation_endpoint.rb +3 -9
  34. data/lib/shrine/plugins/derivatives.rb +26 -17
  35. data/lib/shrine/plugins/entity.rb +24 -16
  36. data/lib/shrine/plugins/included.rb +1 -0
  37. data/lib/shrine/plugins/infer_extension.rb +2 -0
  38. data/lib/shrine/plugins/metadata_attributes.rb +18 -8
  39. data/lib/shrine/plugins/model.rb +35 -14
  40. data/lib/shrine/plugins/remote_url.rb +2 -6
  41. data/lib/shrine/plugins/remove_attachment.rb +2 -6
  42. data/lib/shrine/plugins/remove_invalid.rb +10 -6
  43. data/lib/shrine/plugins/sequel.rb +31 -78
  44. data/lib/shrine/plugins/upload_options.rb +2 -2
  45. data/lib/shrine/plugins/validation.rb +1 -11
  46. data/lib/shrine/version.rb +1 -1
  47. metadata +4 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 36715577aa30205e12419931f31b3dfad46e30e659372c88e5e926d536984dfc
4
- data.tar.gz: fd74dd99deef2030ebc5c2935bccb15447e5a5eb9a916c8379e6d57db87bba23
3
+ metadata.gz: c5f2d3f6519d99e728cdfffe80783d0278f171bb6f8a850b4840d2d9fb92eda5
4
+ data.tar.gz: 28566d4950a3ad23cb657e699db8a0861283efb8709a7a70d6a20c83d8a5c0c7
5
5
  SHA512:
6
- metadata.gz: 2fbc8cce3080e6728d04c59e6e56b2653b47df3c0d8dece92f62590cebcd5d30a54c9f7f31ba11ff6fcf6041190438ee20785075c7ca3dce6863ac77311ca69b
7
- data.tar.gz: '038a34aade2923b6c5ce0f36d6d8897dc1ac7cc06b06a06dd46cbffc26cc57db0345ead5674562ac1d84a7a8825e49a8a536ce0321321d7edbf3f429795fa492'
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
@@ -240,7 +240,7 @@ particular storage.
240
240
 
241
241
  ```rb
242
242
  class MyUploader < Shrine
243
- # image attachent logic
243
+ # image attachment logic
244
244
  end
245
245
  ```
246
246
 
@@ -71,96 +71,53 @@ end
71
71
 
72
72
  ## Attacher
73
73
 
74
- ### Persistence
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 :atomic_helpers
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
- See the [`activerecord`][activerecord]/[`sequel`][sequel] plugin source code on
126
- how this integration should look like.
87
+ This will define the following attacher methods:
127
88
 
128
- ### With other persistence plugins
89
+ * `Attacher#persist`
90
+ * `Attacher#atomic_persist`
91
+ * `Attacher#atomic_promote`
129
92
 
130
- It's recommended to prefix each of the above methods with the name of the
131
- database library, and make non-prefixed versions aliases.
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
- def raptor_atomic_promote(...)
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 raptor_atomic_persist(...)
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 raptor_persist(...)
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
@@ -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
- ### Atomic promotion
153
+ The following persistence methods are added to the attacher:
154
154
 
155
- If you're promoting cached file to permanent storage
156
- [asynchronously][backgrounding], you might want to handle the possibility of
157
- the attachment changing during promotion. You can do that with
158
- `Attacher#atomic_promote`:
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
- ```rb
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
- [atomic_helpers]: /doc/plugins/atomic_helpers.md#readme
262
- [backgrounding]: /doc/plugins/backgrounding.md#readme
169
+ [persistence]: /doc/plugins/persistence.md#readme
@@ -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, context|
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, context|
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, context|
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
- Any previously extracted metadata can be accessed via `context[:metadata]`:
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, context|
72
- context[:metadata] #=>
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, context|
83
- context[:metadata] #=>
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: photo,
22
- name: :image,
23
- data: { "id" => "...", "storage" => "...", "metadata" => { ... } },
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
- data: { "id" => "...", "storage" => "...", "metadata" => { ... } },
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, data: { ... })
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, data: { ... })
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":"cache","metadata":{...}}'
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
- data: { "id" => "bar", "storage" => "cache", "metadata" => { ... } },
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 before persistence, you can pass a block:
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
- @user.cached_avatar_data #=> '{"id":"38k25.jpg","storage":"cache","metadata":{...}}'
16
+ photo.cached_image_data #=> '{"id":"38k25.jpg","storage":"cache","metadata":{...}}'
17
17
  ```
18
18
 
19
- This method delegates to `Attacher#read_cached`:
19
+ This method delegates to `Attacher#cached_data`:
20
20
 
21
21
  ```rb
22
- attacher.read_cached #=> '{"id":"38k25.jpg","storage":"cache","metadata":{...}}'
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
@@ -7,23 +7,22 @@ This plugin is useful for example when using [HTML5 Canvas].
7
7
  plugin :data_uri
8
8
  ```
9
9
 
10
- If your attachment is called "avatar", this plugin will add `#avatar_data_uri`
11
- and `#avatar_data_uri=` methods to your model.
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
- user.avatar #=> nil
15
- user.avatar_data_uri = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA"
16
- user.avatar #=> #<Shrine::UploadedFile>
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
- You can also use `#data_uri=` and `#data_uri` methods directly on the
23
- `Shrine::Attacher` (which the model methods just delegate to):
19
+ If you're using `Shrine::Attacher` directly, you can use
20
+ `Attacher#assign_data_uri`:
24
21
 
25
22
  ```rb
26
- attacher.data_uri = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA"
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
- ## Upload options
38
+ ## Uploader options
40
39
 
41
- If you want to pass additional options for `Shrine#upload`, you can use
42
- `#assign_data_uri`:
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: { "mime_type" => "text/plain" })
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
- ## API
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
- ### `UploadedFile#data_uri` and `UploadedFile#base64`
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 enables you to change which
4
- storages are going to be used for this uploader's attacher (the default is
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: :special_cache, store: :special_store
8
+ plugin :default_storage, cache: :other_cache, store: :other_store
9
9
  ```
10
10
 
11
- You can also pass a block and choose the values depending on the record values
12
- and the name of the attachment. This is useful if you're using the
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: ->(record, name) { :"store_#{record.username}" }
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