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
data/doc/plugins/default_url.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Default URL
|
2
2
|
|
3
3
|
The [`default_url`][default_url] plugin allows setting the URL which will be
|
4
|
-
returned when
|
4
|
+
returned when there is no attached file.
|
5
5
|
|
6
6
|
```rb
|
7
7
|
plugin :default_url
|
@@ -11,13 +11,24 @@ Attacher.default_url do |options|
|
|
11
11
|
end
|
12
12
|
```
|
13
13
|
|
14
|
-
`Attacher#url`
|
15
|
-
|
14
|
+
The `Attacher#url` method will return the default URL when attachment is
|
15
|
+
missing:
|
16
16
|
|
17
17
|
```rb
|
18
|
-
attacher.url #=> "/avatar/missing.jpg"
|
19
|
-
# or
|
20
18
|
user.avatar_url #=> "/avatar/missing.jpg"
|
19
|
+
# or
|
20
|
+
attacher.url #=> "/avatar/missing.jpg"
|
21
|
+
```
|
22
|
+
|
23
|
+
Any URL options passed will be available in the default URL block:
|
24
|
+
|
25
|
+
```rb
|
26
|
+
attacher.url(foo: "bar")
|
27
|
+
```
|
28
|
+
```rb
|
29
|
+
Attacher.default_url do |options|
|
30
|
+
options #=> { foo: "bar" }
|
31
|
+
end
|
21
32
|
```
|
22
33
|
|
23
34
|
The default URL block is evaluated in the context of an instance of
|
@@ -25,10 +36,11 @@ The default URL block is evaluated in the context of an instance of
|
|
25
36
|
|
26
37
|
```rb
|
27
38
|
Attacher.default_url do |options|
|
28
|
-
self
|
39
|
+
self #=> #<Shrine::Attacher>
|
29
40
|
|
30
|
-
name
|
31
|
-
record
|
41
|
+
name #=> :avatar
|
42
|
+
record #=> #<User>
|
43
|
+
context #=> { ... }
|
32
44
|
end
|
33
45
|
```
|
34
46
|
|
@@ -41,7 +53,7 @@ option:
|
|
41
53
|
plugin :default_url, host: "https://example.com"
|
42
54
|
```
|
43
55
|
```rb
|
44
|
-
|
56
|
+
attacher.url #=> "https://example.com/avatar/missing.jpg"
|
45
57
|
```
|
46
58
|
|
47
59
|
[default_url]: /lib/shrine/plugins/default_url.rb
|
@@ -28,6 +28,7 @@ process them on-the-fly.
|
|
28
28
|
- [Skipping download](#skipping-download)
|
29
29
|
* [Derivation API](#derivation-api)
|
30
30
|
* [Plugin Options](#plugin-options)
|
31
|
+
* [Instrumentation](#instrumentation)
|
31
32
|
|
32
33
|
## Quick start
|
33
34
|
|
@@ -785,6 +786,53 @@ derivation.option(:upload_location)
|
|
785
786
|
| `:upload_storage` | Storage to which the derivations will be uploaded | same storage as the source file |
|
786
787
|
| `:version` | Version number to append to the URL for cache busting | `nil` |
|
787
788
|
|
789
|
+
## Instrumentation
|
790
|
+
|
791
|
+
If the `instrumentation` plugin has been loaded, the `determine_mime_type` plugin
|
792
|
+
adds instrumentation around derivation processing.
|
793
|
+
|
794
|
+
```rb
|
795
|
+
# instrumentation plugin needs to be loaded *before* derivation_endpoint
|
796
|
+
plugin :instrumentation
|
797
|
+
plugin :derivation_endpoint
|
798
|
+
```
|
799
|
+
|
800
|
+
Derivation processing will trigger a `derivation.shrine` event with the
|
801
|
+
following payload:
|
802
|
+
|
803
|
+
| Key | Description |
|
804
|
+
| :-- | :---- |
|
805
|
+
| `:derivation` | `Shrine::Derivation` object for this processing |
|
806
|
+
| `:uploader` | The uploader class that sent the event |
|
807
|
+
|
808
|
+
A default log subscriber is added as well which logs these events:
|
809
|
+
|
810
|
+
```
|
811
|
+
Derivation (492ms) – {:name=>:thumbnail, :args=>[600, 600], :uploader=>Shrine}
|
812
|
+
```
|
813
|
+
|
814
|
+
You can also use your own log subscriber:
|
815
|
+
|
816
|
+
```rb
|
817
|
+
plugin :derivation_endpoint, log_subscriber: -> (event) {
|
818
|
+
Shrine.logger.info JSON.generate(
|
819
|
+
name: event.name,
|
820
|
+
duration: event.duration,
|
821
|
+
name: event[:derivation].name,
|
822
|
+
args: event[:derivation].args,
|
823
|
+
)
|
824
|
+
}
|
825
|
+
```
|
826
|
+
```
|
827
|
+
{"name":"derivation","duration":492,"name":"thumbnail","args":[600,600],"uploader":"Shrine"}
|
828
|
+
```
|
829
|
+
|
830
|
+
Or disable logging altogether:
|
831
|
+
|
832
|
+
```rb
|
833
|
+
plugin :derivation_endpoint, log_subscriber: nil
|
834
|
+
```
|
835
|
+
|
788
836
|
[derivation_endpoint]: /lib/shrine/plugins/derivation_endpoint.rb
|
789
837
|
[ImageProcessing]: https://github.com/janko/image_processing
|
790
838
|
[`Content-Type`]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type
|
data/doc/plugins/derivatives.md
CHANGED
@@ -12,6 +12,7 @@ plugin :derivatives
|
|
12
12
|
|
13
13
|
* [API overview](#api-overview)
|
14
14
|
* [Creating derivatives](#creating-derivatives)
|
15
|
+
- [Derivatives storage](#derivatives-storage)
|
15
16
|
- [Nesting derivatives](#nesting-derivatives)
|
16
17
|
* [Retrieving derivatives](#retrieving-derivatives)
|
17
18
|
* [Derivative URL](#derivative-url)
|
@@ -20,7 +21,6 @@ plugin :derivatives
|
|
20
21
|
- [Source file](#source-file)
|
21
22
|
* [Adding derivatives](#adding-derivatives)
|
22
23
|
* [Uploading derivatives](#uploading-derivatives)
|
23
|
-
- [Derivatives storage](#derivatives-storage)
|
24
24
|
- [Uploader options](#uploader-options)
|
25
25
|
- [File deletion](#file-deletion)
|
26
26
|
* [Merging derivatives](#merging-derivatives)
|
@@ -50,8 +50,8 @@ class, and it's layered in the following way:
|
|
50
50
|
|
51
51
|
When you have a file attached, you can generate derivatives from it and save
|
52
52
|
them alongside the attached file. The simplest way to do this is to define a
|
53
|
-
processor which returns the processed files, and then trigger it
|
54
|
-
|
53
|
+
processor which returns the processed files, and then trigger it when you want
|
54
|
+
to create derivatives.
|
55
55
|
|
56
56
|
Here is an example of generating image thumbnails:
|
57
57
|
|
@@ -85,7 +85,7 @@ end
|
|
85
85
|
photo.image #=> #<Shrine::UploadedFile @id="original.jpg" @storage_key=:store ...>
|
86
86
|
photo.image_derivatives #=> {}
|
87
87
|
|
88
|
-
photo.
|
88
|
+
photo.image_derivatives!(:thumbnails) # calls registered processor and uploads results
|
89
89
|
photo.image_derivatives #=>
|
90
90
|
# {
|
91
91
|
# small: #<Shrine::UploadedFile @id="small.jpg" @storage_key=:store ...>,
|
@@ -111,12 +111,68 @@ photo.image_data #=>
|
|
111
111
|
# }
|
112
112
|
```
|
113
113
|
|
114
|
-
|
115
|
-
|
114
|
+
When using `Shrine::Attacher` directly, derivatives are created using
|
115
|
+
`Attacher#create_derivatives`:
|
116
|
+
|
117
|
+
```rb
|
118
|
+
attacher.file #=> #<Shrine::UploadedFile @id="original.jpg" @storage_key=:store ...>
|
119
|
+
attacher.derivatives #=> {}
|
120
|
+
|
121
|
+
attacher.create_derivatives(:thumbnails) # calls registered processor and uploads results
|
122
|
+
attacher.derivatives #=>
|
123
|
+
# {
|
124
|
+
# small: #<Shrine::UploadedFile @id="small.jpg" @storage_key=:store ...>,
|
125
|
+
# medium: #<Shrine::UploadedFile @id="medium.jpg" @storage_key=:store ...>,
|
126
|
+
# large: #<Shrine::UploadedFile @id="large.jpg" @storage_key=:store ...>,
|
127
|
+
# }
|
128
|
+
```
|
129
|
+
|
130
|
+
### Derivatives storage
|
131
|
+
|
132
|
+
By default, derivatives are uploaded to the permanent storage of the attacher.
|
133
|
+
You can change the default destination storage with the `:storage` plugin
|
134
|
+
option:
|
116
135
|
|
117
136
|
```rb
|
118
|
-
|
119
|
-
|
137
|
+
plugin :derivatives, storage: :other_store
|
138
|
+
```
|
139
|
+
|
140
|
+
The storage can be dynamic based on the derivative name:
|
141
|
+
|
142
|
+
```rb
|
143
|
+
plugin :derivatives, storage: -> (derivative) do
|
144
|
+
if derivative == :thumb
|
145
|
+
:thumbnail_store
|
146
|
+
else
|
147
|
+
:store
|
148
|
+
end
|
149
|
+
end
|
150
|
+
```
|
151
|
+
|
152
|
+
You can also set this option with `Attacher.derivatives_storage`:
|
153
|
+
|
154
|
+
```rb
|
155
|
+
Attacher.derivatives_storage :other_store
|
156
|
+
# or
|
157
|
+
Attacher.derivatives_storage do |derivative|
|
158
|
+
if derivative == :thumb
|
159
|
+
:thumbnail_store
|
160
|
+
else
|
161
|
+
:store
|
162
|
+
end
|
163
|
+
end
|
164
|
+
```
|
165
|
+
|
166
|
+
The storage block is evaluated in the context of a `Shrine::Attacher` instance:
|
167
|
+
|
168
|
+
```rb
|
169
|
+
Attacher.derivatives_storage do |derivative|
|
170
|
+
self #=> #<Shrine::Attacher>
|
171
|
+
|
172
|
+
record #=> #<Photo>
|
173
|
+
name #=> :image
|
174
|
+
context #=> { ... }
|
175
|
+
end
|
120
176
|
```
|
121
177
|
|
122
178
|
### Nesting derivatives
|
@@ -284,8 +340,8 @@ Attacher.derivatives_processor :my_processor do |original|
|
|
284
340
|
end
|
285
341
|
```
|
286
342
|
|
287
|
-
Moreover, any options passed to `Attacher#process_derivatives`
|
288
|
-
forwarded to the processor:
|
343
|
+
Moreover, any options passed to `Attacher#process_derivatives` (or
|
344
|
+
`Attacher#create_derivatives`) will be forwarded to the processor:
|
289
345
|
|
290
346
|
```rb
|
291
347
|
attacher.process_derivatives(:my_processor, foo: "bar")
|
@@ -315,7 +371,7 @@ attacher.process_derivatives(:my_processor) # downloads attached file and passes
|
|
315
371
|
If you already have the source file locally, or if you're calling multiple
|
316
372
|
processors in a row and want to avoid downloading the same source file each
|
317
373
|
time, you can pass the source file as the second argument to
|
318
|
-
`Attacher#process_derivatives
|
374
|
+
`Attacher#process_derivatives` (or `Attacher#create_derivatives`):
|
319
375
|
|
320
376
|
```rb
|
321
377
|
# this way the source file is downloaded only once
|
@@ -406,63 +462,18 @@ attacher.upload_derivative(:thumb, thumbnail_file)
|
|
406
462
|
#=> #<Shrine::UploadedFile>
|
407
463
|
```
|
408
464
|
|
409
|
-
###
|
410
|
-
|
411
|
-
By default, derivatives are uploaded to the permanent storage of the attacher
|
412
|
-
(`:store` by default). You can specify a different destination storage for
|
413
|
-
`Attacher#upload_derivative(s)` with the `:storage` option:
|
414
|
-
|
415
|
-
```rb
|
416
|
-
attacher.upload_derivatives(derivatives, storage: :other_store)
|
417
|
-
```
|
418
|
-
|
419
|
-
You can also set a default derivatives storage on the plugin level:
|
420
|
-
|
421
|
-
```rb
|
422
|
-
plugin :derivatives, storage: :other_store
|
423
|
-
```
|
424
|
-
|
425
|
-
The storage can be dynamic based on the derivative name:
|
426
|
-
|
427
|
-
```rb
|
428
|
-
plugin :derivatives, storage: -> (derivative) do
|
429
|
-
if derivative == :thumb
|
430
|
-
:thumbnail_store
|
431
|
-
else
|
432
|
-
:store
|
433
|
-
end
|
434
|
-
end
|
435
|
-
```
|
436
|
-
|
437
|
-
You can also set this option with `Attacher.derivatives_storage`:
|
438
|
-
|
439
|
-
```rb
|
440
|
-
Attacher.derivatives_storage :other_store
|
441
|
-
# or
|
442
|
-
Attacher.derivatives_storage do |derivative|
|
443
|
-
if derivative == :thumb
|
444
|
-
:thumbnail_store
|
445
|
-
else
|
446
|
-
:store
|
447
|
-
end
|
448
|
-
end
|
449
|
-
```
|
465
|
+
### Uploader options
|
450
466
|
|
451
|
-
|
467
|
+
You can specify the destination storage by passing `:storage` option to
|
468
|
+
`Attacher#upload_derivative(s)`. This will override the [default derivatives
|
469
|
+
storage](#derivatives-storage) setting.
|
452
470
|
|
453
471
|
```rb
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
record #=> #<Photo>
|
458
|
-
name #=> :image
|
459
|
-
context #=> { ... }
|
460
|
-
end
|
472
|
+
attacher.upload_derivative(:thumb, thumnbail_file, storage: :other_store)
|
473
|
+
#=> #<Shrine::UploadedFile @id="thumb.jpg" @storage_key=:other_store ...>
|
461
474
|
```
|
462
475
|
|
463
|
-
|
464
|
-
|
465
|
-
Any options other than `:storage` will be forwarded to the uploader:
|
476
|
+
Any other options will be forwarded to the uploader:
|
466
477
|
|
467
478
|
```rb
|
468
479
|
attacher.upload_derivative :thumb, thumbnail_file,
|
data/doc/plugins/entity.md
CHANGED
@@ -102,6 +102,19 @@ attacher = photo.image_attacher
|
|
102
102
|
attacher.store_key #=> :other_store
|
103
103
|
```
|
104
104
|
|
105
|
+
You can retrieve an `Attacher` instance from the entity *class* as well. In
|
106
|
+
this case it will not be initialized with any entity instance.
|
107
|
+
|
108
|
+
```rb
|
109
|
+
attacher = Photo.image_attacher
|
110
|
+
attacher #=> #<ImageUploader::Attacher>
|
111
|
+
attacher.record #=> nil
|
112
|
+
attacher.name #=> nil
|
113
|
+
|
114
|
+
attacher = Photo.image_attacher(store: :other_store)
|
115
|
+
attacher.store_key #=> :other_store
|
116
|
+
```
|
117
|
+
|
105
118
|
## Attacher
|
106
119
|
|
107
120
|
### Loading entity
|
@@ -133,9 +146,21 @@ You can also load an entity into an existing attacher with
|
|
133
146
|
```rb
|
134
147
|
photo = Photo.new(image_data: '{"id":"...","storage":"...","metadata":{...}}')
|
135
148
|
|
136
|
-
attacher.file #=> nil
|
137
149
|
attacher.load_entity(photo, :image)
|
138
|
-
attacher.
|
150
|
+
attacher.record #=> #<Photo>
|
151
|
+
attacher.name #=> :image
|
152
|
+
attacher.file #=> #<ImageUploader::UploadedFile>
|
153
|
+
```
|
154
|
+
|
155
|
+
Or just `Attacher#set_entity` if you don't want to load attachment data:
|
156
|
+
|
157
|
+
```rb
|
158
|
+
photo = Photo.new(image_data: '{"id":"...","storage":"...","metadata":{...}}')
|
159
|
+
|
160
|
+
attacher.set_entity(photo, :image) # doesn't load attachment data
|
161
|
+
attacher.record #=> #<Photo>
|
162
|
+
attacher.name #=> :image
|
163
|
+
attacher.file #=> nil
|
139
164
|
```
|
140
165
|
|
141
166
|
### Reloading
|
data/doc/plugins/included.md
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
# Included
|
2
2
|
|
3
3
|
The [`included`][included] plugin allows you to hook up to the `.included` hook
|
4
|
-
of the attachment module, and call additional methods on the model
|
4
|
+
of the attachment module, and call additional methods on the model that
|
5
5
|
includes it.
|
6
6
|
|
7
7
|
```rb
|
8
8
|
plugin :included do |name|
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
# called when attachment module is included into a model
|
10
|
+
|
11
|
+
self #=> #<Photo>
|
12
|
+
name #=> :image
|
12
13
|
end
|
13
14
|
```
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
```rb
|
16
|
+
Photo.include Shrine::Attachment(:image)
|
17
|
+
```
|
17
18
|
|
18
19
|
[included]: /lib/shrine/plugins/included.rb
|
@@ -7,7 +7,9 @@ method:
|
|
7
7
|
|
8
8
|
```rb
|
9
9
|
plugin :metadata_attributes, :size => :size, :mime_type => :type
|
10
|
+
|
10
11
|
# or
|
12
|
+
|
11
13
|
plugin :metadata_attributes
|
12
14
|
Attacher.metadata_attributes :size => :size, :mime_type => :type
|
13
15
|
```
|
@@ -28,19 +30,32 @@ user.avatar_size #=> nil
|
|
28
30
|
user.avatar_type #=> nil
|
29
31
|
```
|
30
32
|
|
33
|
+
If you're using the [`entity`][entity] plugin, metadata attributes will be
|
34
|
+
added to `Attacher#column_values`:
|
35
|
+
|
36
|
+
```rb
|
37
|
+
attacher.assign(io)
|
38
|
+
attacher.column_values #=>
|
39
|
+
# {
|
40
|
+
# :image_data => '{ ... }',
|
41
|
+
# :image_size => 95724,
|
42
|
+
# :image_type => "image/jpeg",
|
43
|
+
# }
|
44
|
+
```
|
45
|
+
|
31
46
|
If you want to specify the full record attribute name, pass the record
|
32
47
|
attribute name as a string instead of a symbol.
|
33
48
|
|
34
49
|
```rb
|
35
50
|
Attacher.metadata_attributes :filename => "original_filename"
|
36
|
-
|
37
|
-
|
38
|
-
|
51
|
+
```
|
52
|
+
```rb
|
39
53
|
photo.image = image
|
40
54
|
photo.original_filename #=> "nature.jpg"
|
41
55
|
```
|
42
56
|
|
43
|
-
|
44
|
-
|
57
|
+
Any metadata attributes that were declared but are missing on the record will
|
58
|
+
be skipped.
|
45
59
|
|
46
60
|
[metadata_attributes]: /lib/shrine/plugins/metadata_attributes.rb
|
61
|
+
[entity]: /doc/plugins/entity.md#readme
|
data/doc/plugins/model.md
CHANGED
@@ -41,6 +41,17 @@ photo.image.storage_key #=> :cache
|
|
41
41
|
photo.image_data #=> '{"id":"...","storage":"cache","metadata":{...}}'
|
42
42
|
```
|
43
43
|
|
44
|
+
#### `#<name>_changed?`
|
45
|
+
|
46
|
+
Calls `Attacher#changed?` which returns whether the attachment has changed.
|
47
|
+
|
48
|
+
```rb
|
49
|
+
photo = Photo.new
|
50
|
+
photo.image_changed? #=> false
|
51
|
+
photo.image = file
|
52
|
+
photo.image_changed? #=> true
|
53
|
+
```
|
54
|
+
|
44
55
|
#### Disabling caching
|
45
56
|
|
46
57
|
If you don't want to use temporary storage, you can have `#<name>=` upload
|
@@ -118,14 +129,23 @@ You can also load an entity into an existing attacher with
|
|
118
129
|
`Attacher#load_model`.
|
119
130
|
|
120
131
|
```rb
|
121
|
-
photo
|
122
|
-
attacher = ImageUploader::Attacher.from_model(photo, :image)
|
132
|
+
photo = Photo.new(image_data: '{"id":"...","storage":"...","metadata":{...}}')
|
123
133
|
|
124
134
|
attacher.file #=> nil
|
125
135
|
attacher.load_model(photo, :image)
|
126
136
|
attacher.file #=> #<ImageUploader::UploadedFile>
|
127
137
|
```
|
128
138
|
|
139
|
+
Or just `Attacher#set_model` if you don't want to load attachment data:
|
140
|
+
|
141
|
+
```rb
|
142
|
+
photo = Photo.new(image_data: '{"id":"...","storage":"...","metadata":{...}}')
|
143
|
+
|
144
|
+
attacher.file #=> nil
|
145
|
+
attacher.set_model(photo, :image) # doesn't load attachment data
|
146
|
+
attacher.file #=> nil
|
147
|
+
```
|
148
|
+
|
129
149
|
### Writing attachment data
|
130
150
|
|
131
151
|
The `Attacher#write` method writes attachment data to the `#<name>_data`
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# Persistence
|
2
|
+
|
3
|
+
This is an internal plugin that provides uniform persistence interface across
|
4
|
+
different persistence plugins (e.g. [`activerecord`][activerecord],
|
5
|
+
[`sequel`][sequel]).
|
6
|
+
|
7
|
+
## Atomic promotion
|
8
|
+
|
9
|
+
If you're promoting cached file to permanent storage
|
10
|
+
[asynchronously][backgrounding], and want to handle the possibility of
|
11
|
+
attachment changing during promotion, you can use `Attacher#atomic_promote`:
|
12
|
+
|
13
|
+
```rb
|
14
|
+
# in your controller
|
15
|
+
attacher.attach_cached(io)
|
16
|
+
attacher.cached? #=> true
|
17
|
+
```
|
18
|
+
```rb
|
19
|
+
# in a background job
|
20
|
+
attacher.atomic_promote # promotes cached file and persists
|
21
|
+
attacher.stored? #=> true
|
22
|
+
```
|
23
|
+
|
24
|
+
After the cached file is uploaded to permanent storage, the record is reloaded
|
25
|
+
in order to check whether the attachment hasn't changed, and if it hasn't the
|
26
|
+
attachment is persisted. If the attachment has changed,
|
27
|
+
`Shrine::AttachmentChanged` exception is raised.
|
28
|
+
|
29
|
+
If you want to execute code after the attachment change check but before
|
30
|
+
persistence, you can pass a block:
|
31
|
+
|
32
|
+
```rb
|
33
|
+
attacher.atomic_promote do |reloaded_attacher|
|
34
|
+
# run code after attachment change check but before persistence
|
35
|
+
end
|
36
|
+
```
|
37
|
+
|
38
|
+
You can pass `:reload` and `:persist` options to change how the record is
|
39
|
+
reloaded and pesisted. See the [`atomic_helpers`][atomic_helpers] plugin docs
|
40
|
+
for more details.
|
41
|
+
|
42
|
+
Any other options are forwarded to `Attacher#promote`:
|
43
|
+
|
44
|
+
```rb
|
45
|
+
attacher.atomic_promote(metadata: true) # re-extract metadata
|
46
|
+
```
|
47
|
+
|
48
|
+
## Atomic persistence
|
49
|
+
|
50
|
+
If you're updating something based on the attached file
|
51
|
+
[asynchronously][backgrounding], you might want to handle the possibility of
|
52
|
+
the attachment changing in the meanwhile. You can do that with
|
53
|
+
`Attacher#atomic_persist`:
|
54
|
+
|
55
|
+
```rb
|
56
|
+
# in a background job
|
57
|
+
attacher.refresh_metadata! # refresh_metadata plugin
|
58
|
+
attacher.atomic_persist # persists attachment data
|
59
|
+
```
|
60
|
+
|
61
|
+
The record is first reloaded in order to check whether the attachment hasn't
|
62
|
+
changed, and if it hasn't the attachment is persisted. If the attachment has
|
63
|
+
changed, `Shrine::AttachmentChanged` exception is raised.
|
64
|
+
|
65
|
+
If you want to execute code after the attachment change check but before
|
66
|
+
persistence, you can pass a block:
|
67
|
+
|
68
|
+
```rb
|
69
|
+
attacher.atomic_persist do |reloaded_attacher|
|
70
|
+
# run code after attachment change check but before persistence
|
71
|
+
end
|
72
|
+
```
|
73
|
+
|
74
|
+
You can pass `:reload` and `:persist` options to change how the record is
|
75
|
+
reloaded and pesisted. See the [`atomic_helpers`][atomic_helpers] plugin docs
|
76
|
+
for more details.
|
77
|
+
|
78
|
+
## Simple Persistence
|
79
|
+
|
80
|
+
To simply save attachment changes to the underlying record, use
|
81
|
+
`Attacher#persist`:
|
82
|
+
|
83
|
+
```rb
|
84
|
+
attacher.attach(io)
|
85
|
+
attacher.persist # saves the underlying record
|
86
|
+
```
|
87
|
+
|
88
|
+
[activerecord]: /doc/plugins/activerecord.md#readme
|
89
|
+
[sequel]: /doc/plugins/sequel.md#readme
|