shrine 3.2.2 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +36 -0
- data/README.md +5 -0
- data/doc/advantages.md +1 -1
- data/doc/carrierwave.md +7 -4
- data/doc/direct_s3.md +1 -0
- data/doc/external/articles.md +6 -8
- data/doc/external/extensions.md +3 -0
- data/doc/external/misc.md +23 -8
- data/doc/getting_started.md +4 -8
- data/doc/multiple_files.md +1 -1
- data/doc/paperclip.md +14 -5
- data/doc/plugins/add_metadata.md +20 -0
- data/doc/plugins/atomic_helpers.md +41 -3
- data/doc/plugins/derivatives.md +43 -12
- data/doc/plugins/download_endpoint.md +5 -5
- data/doc/plugins/dynamic_storage.md +1 -1
- data/doc/plugins/infer_extension.md +9 -0
- data/doc/plugins/metadata_attributes.md +1 -0
- data/doc/plugins/mirroring.md +1 -1
- data/doc/plugins/persistence.md +10 -1
- data/doc/plugins/store_dimensions.md +10 -0
- data/doc/plugins/url_options.md +2 -2
- data/doc/processing.md +7 -8
- data/doc/release_notes/2.8.0.md +1 -1
- data/doc/release_notes/3.2.1.md +2 -3
- data/doc/release_notes/3.3.0.md +105 -0
- data/doc/storage/s3.md +9 -5
- data/doc/upgrading_to_3.md +11 -27
- data/lib/shrine/attacher.rb +6 -1
- data/lib/shrine/plugins/activerecord.rb +1 -1
- data/lib/shrine/plugins/add_metadata.rb +6 -4
- data/lib/shrine/plugins/backgrounding.rb +2 -2
- data/lib/shrine/plugins/derivation_endpoint.rb +2 -1
- data/lib/shrine/plugins/derivatives.rb +45 -15
- data/lib/shrine/plugins/mirroring.rb +8 -8
- data/lib/shrine/plugins/presign_endpoint.rb +14 -2
- data/lib/shrine/plugins/remove_attachment.rb +5 -0
- data/lib/shrine/plugins/sequel.rb +1 -1
- data/lib/shrine/plugins/store_dimensions.rb +4 -2
- data/lib/shrine/plugins/upload_endpoint.rb +7 -2
- data/lib/shrine/storage/memory.rb +5 -3
- data/lib/shrine/storage/s3.rb +61 -6
- data/lib/shrine/version.rb +2 -2
- data/shrine.gemspec +1 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8cfa59ed1f6143ee9298ede17eeda07dba85f0f9c3309a5b7a9e7f6c41399f29
|
4
|
+
data.tar.gz: 67a64a3a4f40c34797ca04279af73829acf4071eb118f78addefdbaa15e048da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e87a3dbb80a304f8af559b9c3d4e8badf8e47e4377afd74fe08d570042d65358d44878c4a0366fa3cded98fe166083275e86c61f3b51d28d35e070e0233dea35
|
7
|
+
data.tar.gz: 83c93e76bf5513ab317ccabbdda86ce90f760e7b898dc9f40036af3e7ec915f48e55bd6f8efcf8661dacea672ce6b24b450db217815b062881169c8c90fd0cd3
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,39 @@
|
|
1
|
+
## 3.3.0 (2020-10-04)
|
2
|
+
|
3
|
+
* `s3` - Support new `Aws::S3::EncryptionV2::Client` for client-side encryption (@janko)
|
4
|
+
|
5
|
+
* `derivation_endpoint` – Reduce possibility of timing attacks when comparing signatures (@esparta)
|
6
|
+
|
7
|
+
* `derivatives` – Avoid downloading the attached file when calling default no-op processor (@janko)
|
8
|
+
|
9
|
+
* `derivatives` – Add `:download` processor setting for skipping downloading source file (@jrochkind, @janko)
|
10
|
+
|
11
|
+
* `derivatives` – Copy non-file source IO objects into local file before passing them to the processor (@jrochkind)
|
12
|
+
|
13
|
+
* `sequel` – Call `Attacher#reload` in `Sequel::Model#reload`, which keeps rest of attacher state (@janko, @jrochkind)
|
14
|
+
|
15
|
+
* `activerecord` – Call `Attacher#reload` in `ActiveRecord::Base#reload`, which keeps rest of attacher state (@janko, @jrochkind)
|
16
|
+
|
17
|
+
* `add_metadata` – Add `:skip_nil` option for excluding metadata keys whose values are nil (@renchap)
|
18
|
+
|
19
|
+
* `store_dimensions` – Add `:auto_extraction` option for disabling automatically extracting dimensions on upload (@renchap)
|
20
|
+
|
21
|
+
* `mirroring` – Forward original upload options when mirroring upload (@corneverbruggen)
|
22
|
+
|
23
|
+
* `derivation_endpoint` – Apply `version` URL option in derivation endpoint (@janko)
|
24
|
+
|
25
|
+
* `remove_attachment` – Delete removed file if a new file was attached right after removal (@janko)
|
26
|
+
|
27
|
+
* `upload_endpoint` – Fix `Shrine.upload_response` not working in a Rails controller (@pldavid2)
|
28
|
+
|
29
|
+
* `presign_endpoint` – Add `OPTIONS` route that newer versions of Uppy check (@janko)
|
30
|
+
|
31
|
+
* `derivatives` – Add `:create_on_promote` option for auto-creating derivatives on promotion (@janko)
|
32
|
+
|
33
|
+
* `s3` – Add back support for client-side encryption (@janko)
|
34
|
+
|
35
|
+
* `memory` – Ensure `Memory#open` returns content in original encoding (@jrochkind)
|
36
|
+
|
1
37
|
## 3.2.2 (2020-08-05)
|
2
38
|
|
3
39
|
* `s3` – Fix `S3#open` not working on aws-sdk-core 3.104 and above (@janko)
|
data/README.md
CHANGED
@@ -127,6 +127,10 @@ system.
|
|
127
127
|
* Refile
|
128
128
|
* Active Storage
|
129
129
|
|
130
|
+
## Contributing
|
131
|
+
|
132
|
+
Please refer to the [contributing page][Contributing].
|
133
|
+
|
130
134
|
## Code of Conduct
|
131
135
|
|
132
136
|
Everyone interacting in the Shrine project’s codebases, issue trackers, and
|
@@ -170,3 +174,4 @@ The gem is available as open source under the terms of the [MIT License].
|
|
170
174
|
[Roda]: https://github.com/jeremyevans/roda
|
171
175
|
[CoC]: /CODE_OF_CONDUCT.md
|
172
176
|
[MIT License]: /LICENSE.txt
|
177
|
+
[Contributing]: https://github.com/shrinerb/shrine/blob/master/CONTRIBUTING.md
|
data/doc/advantages.md
CHANGED
@@ -93,7 +93,7 @@ low-level abstractions that give you the flexibility to build your own flow.
|
|
93
93
|
```rb
|
94
94
|
uploaded_file = ImageUploader.upload(image, :store) # metadata extraction, upload location generation
|
95
95
|
uploaded_file.id #=> "44ccafc10ce6a4ff22829e8f579ee6b9.jpg"
|
96
|
-
|
96
|
+
uploaded_file.metadata #=> { ... extracted metadata ... }
|
97
97
|
|
98
98
|
data = uploaded_file.to_json # serialization
|
99
99
|
# ...
|
data/doc/carrierwave.md
CHANGED
@@ -322,19 +322,22 @@ module CarrierwaveShrineSynchronization
|
|
322
322
|
|
323
323
|
private
|
324
324
|
|
325
|
-
# If you'll be using `:prefix` on your Shrine storage, make sure to
|
326
|
-
# subtract it from the path assigned as `:id`.
|
327
325
|
def shrine_file(uploader)
|
328
326
|
name = uploader.mounted_as
|
329
327
|
filename = read_attribute(name)
|
330
|
-
|
328
|
+
location = uploader.store_path(filename)
|
329
|
+
location = location.sub(%r{^#{storage.prefix}/}, "") if storage.prefix
|
331
330
|
|
332
331
|
Shrine.uploaded_file(
|
333
332
|
storage: :store,
|
334
|
-
id:
|
333
|
+
id: location,
|
335
334
|
metadata: { "filename" => filename },
|
336
335
|
)
|
337
336
|
end
|
337
|
+
|
338
|
+
def storage
|
339
|
+
Shrine.storages[:store]
|
340
|
+
end
|
338
341
|
end
|
339
342
|
```
|
340
343
|
```rb
|
data/doc/direct_s3.md
CHANGED
@@ -76,6 +76,7 @@ If you're using [Uppy], this is the recommended CORS configuration for the
|
|
76
76
|
<AllowedHeader>x-amz-content-sha256</AllowedHeader>
|
77
77
|
<AllowedHeader>content-type</AllowedHeader>
|
78
78
|
<AllowedHeader>content-disposition</AllowedHeader>
|
79
|
+
<ExposeHeader>ETag</ExposeHeader>
|
79
80
|
</CORSRule>
|
80
81
|
<CORSRule>
|
81
82
|
<AllowedOrigin>*</AllowedOrigin>
|
data/doc/external/articles.md
CHANGED
@@ -21,7 +21,7 @@ title: Articles
|
|
21
21
|
| [Asynchronous File Uploads](http://twin.github.io/file-uploads-asynchronous-world) | 18 Jan 2016 |
|
22
22
|
| [Introducing Shrine](http://twin.github.io/introducing-shrine) | 04 Oct 2015 |
|
23
23
|
|
24
|
-
##
|
24
|
+
## Community articles
|
25
25
|
|
26
26
|
| Article | Published |
|
27
27
|
| :------ | --------: |
|
@@ -32,9 +32,9 @@ title: Articles
|
|
32
32
|
| [Happy users uploading files with Rails 5, Shrine, and Vue.js](https://itnext.io/happy-users-uploading-files-with-rails-5-shrine-and-vue-js-bbcc470a327f) | 04 Sep 2018 |
|
33
33
|
| [Rails 5 + Shrine + DropzoneJS](https://stephencodes.com/rails-5-shrine-dropzonejs/) | 20 Oct 2018 |
|
34
34
|
| [How to use Trix and Shrine for WYSIWYG Editing with Drag-and-Drop Image Uploading](http://headway.io/blog/how-to-use-trix-and-shrine-for-wysiwyg-editing-with-drag-and-drop-image-uploading/) | 26 Jan 2018 |
|
35
|
-
| [Store Your Files on S3: Uploading from a URL](https://www.ironin.it/blog/store-your-files-on-s3-using-the-ruby-shrine-gem-part-3.html) | 28 Dec 2017 |
|
36
|
-
| [Store Your Files on S3: Direct Uploads](https://www.ironin.it/blog/store-your-files-on-s3-using-the-ruby-shrine-gem-part-2.html) | 15 Dec 2017 |
|
37
|
-
| [Store Your Files on S3: Setup & Configuration](https://www.ironin.it/blog/store-your-files-on-s3-using-the-ruby-shrine-gem-part-1.html) | 27 Nov 2017 |
|
35
|
+
| [Store Your Files on S3: Part 3 – Uploading from a URL](https://www.ironin.it/blog/store-your-files-on-s3-using-the-ruby-shrine-gem-part-3.html) | 28 Dec 2017 |
|
36
|
+
| [Store Your Files on S3: Part 2 – Direct Uploads](https://www.ironin.it/blog/store-your-files-on-s3-using-the-ruby-shrine-gem-part-2.html) | 15 Dec 2017 |
|
37
|
+
| [Store Your Files on S3: Part 1 – Setup & Configuration](https://www.ironin.it/blog/store-your-files-on-s3-using-the-ruby-shrine-gem-part-1.html) | 27 Nov 2017 |
|
38
38
|
| [Creating Streaming Radio With Rails and Icecast](https://scotch.io/tutorials/creating-online-streaming-radio-with-rails-and-icecast) | 06 Nov 2017 |
|
39
39
|
| [Multiple Photo Upload using Shrine](https://github.com/pyksoft/multi-photo-upload#multiple-photo-upload-using-shrine) | 02 Nov 2017 |
|
40
40
|
| [Uploading Files with Rails and ActionCable](https://scotch.io/tutorials/uploading-files-with-rails-and-actioncable) | 19 Oct 2017 |
|
@@ -48,14 +48,12 @@ title: Articles
|
|
48
48
|
|
49
49
|
| Screencast | Source | Published |
|
50
50
|
| :---- | :------ | --------: |
|
51
|
+
| [Testing File Uploads in Rails with Shrine](https://gorails.com/episodes/testing-file-uploads-with-shrine?autoplay=1) | GoRails | 23 Mar 2020 |
|
52
|
+
| [File Uploads in Rails with Shrine](https://gorails.com/episodes/rails-file-uploads-with-shrine?autoplay=1) | GoRails | 16 Mar 2020 |
|
51
53
|
| [Uploading Files to DigitalOcean Spaces](https://gorails.com/episodes/digital-ocean-spaces-with-rails?autoplay=1) | GoRails | 31 Oct 2017 |
|
52
54
|
| [Trix WYSIWYG Editor And File Uploads](https://gorails.com/episodes/trix-editor?autoplay=1) | GoRails | 03 Oct 2017 |
|
53
55
|
| [Multiple File Uploads with Shrine](https://gorails.com/episodes/multiple-file-uploads-with-shrine?autoplay=1) | GoRails | 14 Dec 2016 |
|
54
56
|
| [Backgrounding and Video Transcoding](https://gorails.com/episodes/shrine-background-and-video-transcoding?autoplay=1) | GoRails | 03 Nov 2016 |
|
55
|
-
| [Direct File Uploads to S3: Part 3](https://gorails.com/episodes/direct-file-uploads-to-s3-part-3?autoplay=1) | GoRails | 05 Oct 2016 |
|
56
|
-
| [Direct File Uploads to S3: Part 2](https://gorails.com/episodes/direct-file-uploads-to-s3-part-2?autoplay=1) | GoRails | 05 Oct 2016 |
|
57
|
-
| [Direct File Uploads to S3: Part 1](https://gorails.com/episodes/direct-file-uploads-to-s3-part-1?autoplay=1) | GoRails | 05 Oct 2016 |
|
58
|
-
| [File Uploads in Rails with Shrine](https://gorails.com/episodes/file-uploading-with-shrine?autoplay=1) | GoRails | 23 Sep 2016 |
|
59
57
|
|
60
58
|
## Talks
|
61
59
|
|
data/doc/external/extensions.md
CHANGED
@@ -28,6 +28,8 @@ title: Extensions
|
|
28
28
|
| :---- | :-------- |
|
29
29
|
| [administrate-field-shrine](https://github.com/catsky/administrate-field-shrine) | Plugin for [Administrate](https://github.com/thoughtbot/administrate) |
|
30
30
|
| [rails_admin_shrine](https://github.com/iquest/rails_admin_shrine) | Plugin for [RailsAdmin](https://github.com/sferik/rails_admin) |
|
31
|
+
| [shrine-blurhash](https://github.com/renchap/shrine-blurhash) | Plugin for computing [Blurhash](https://blurha.sh/) on images |
|
32
|
+
| [shrine-cloudimage](https://github.com/janklimo/shrine-cloudimage) | Plugin for [Cloudimage](https://www.cloudimage.io/) |
|
31
33
|
| [shrine-color](https://github.com/jnylen/shrine-color) | Plugin for finding dominant color in an image |
|
32
34
|
| [shrine-configurable_storage](https://github.com/SleeplessByte/shrine-configurable_storage) | Plugin for lazy storage registration |
|
33
35
|
| [shrine-content_addressable](https://github.com/SleeplessByte/shrine-content_addressable) | Plugin for generating content addressable locations |
|
@@ -45,6 +47,7 @@ title: Extensions
|
|
45
47
|
| Gem | Description |
|
46
48
|
| :----- | :------- |
|
47
49
|
| [ckeditor](https://github.com/galetahub/ckeditor) | Integration for [CKEditor](https://ckeditor.com/ckeditor-4/) |
|
50
|
+
| [faster_s3_url](https://github.com/jrochkind/faster_s3_url) | Optimized generation of public and presigned AWS S3 GET URLs |
|
48
51
|
| [imgproxy](https://github.com/imgproxy/imgproxy.rb) | Integration for [imgproxy](https://github.com/imgproxy/imgproxy) |
|
49
52
|
| [rails_admin](https://github.com/sferik/rails_admin) | Integration for [RailsAdmin](https://github.com/sferik/rails_admin) |
|
50
53
|
| [uppy-s3_multipart](https://github.com/janko/uppy-s3_multipart) | Integration for [Uppy AWS S3 Multipart](https://uppy.io/docs/aws-s3-multipart/) |
|
data/doc/external/misc.md
CHANGED
@@ -4,14 +4,29 @@ title: Miscellaneous
|
|
4
4
|
|
5
5
|
## Demos
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
7
|
+
| Demo | Description |
|
8
|
+
| :--- | :---------- |
|
9
|
+
| [Dropzone demo](https://github.com/codyeatworld/example-shrine-dropzone) | Shows direct upload using [Dropzone.js] |
|
10
|
+
| [Hanami demo](https://github.com/katafrakt/hanami-shrine-example) | Shows file attachment in [Hanami] |
|
11
|
+
| [Crop demo](https://github.com/shrinerb/shrine-crop-example) | Shows image cropping using [Cropper.js] |
|
12
|
+
| [Rails demo](https://github.com/erikdahlstrand/shrine-rails-example) | Shows direct upload in [Rails] |
|
13
|
+
| [Resumable uploads demo](https://github.com/shrinerb/shrine-tus-demo) | Shows resumable direct upload on [tus] |
|
14
|
+
| [Roda demo (official)](https://github.com/shrinerb/shrine/tree/master/demo) | Shows direct upload in [Roda] |
|
15
|
+
| [rom-rb & dry-rb demo](https://github.com/shrinerb/shrine-rom/tree/master/demo) | Shows file attachment with [rom-rb] and [dry-rb] |
|
16
|
+
| [Transloadit demo](https://github.com/shrinerb/shrine-transloadit/tree/master/demo) | Shows file processing using [Transloadit] |
|
14
17
|
|
15
18
|
## Projects
|
16
19
|
|
17
|
-
|
20
|
+
| Project | Description |
|
21
|
+
| :------ | :---------- |
|
22
|
+
| [CortexCMS](https://docs.cortexcms.org) | An open source, enterprise content management and distribution platform |
|
23
|
+
|
24
|
+
[Dropzone.js]: https://www.dropzonejs.com/
|
25
|
+
[Hanami]: https://hanamirb.org/
|
26
|
+
[Cropper.js]: https://github.com/fengyuanchen/cropperjs
|
27
|
+
[Rails]: https://rubyonrails.org/
|
28
|
+
[tus]: https://tus.io/
|
29
|
+
[Roda]: https://roda.jeremyevans.net/
|
30
|
+
[rom-rb]: https://rom-rb.org/
|
31
|
+
[dry-rb]: https://dry-rb.org/
|
32
|
+
[Transloadit]: https://transloadit.com/
|
data/doc/getting_started.md
CHANGED
@@ -554,7 +554,7 @@ creation:
|
|
554
554
|
gem "image_processing", "~> 1.8"
|
555
555
|
```
|
556
556
|
```rb
|
557
|
-
Shrine.plugin :derivatives
|
557
|
+
Shrine.plugin :derivatives, create_on_promote: true
|
558
558
|
```
|
559
559
|
```rb
|
560
560
|
require "image_processing/mini_magick"
|
@@ -573,11 +573,7 @@ end
|
|
573
573
|
```
|
574
574
|
```rb
|
575
575
|
photo = Photo.new(image: file)
|
576
|
-
|
577
|
-
if photo.valid?
|
578
|
-
photo.image_derivatives! if photo.image_changed? # create derivatives
|
579
|
-
photo.save
|
580
|
-
end
|
576
|
+
photo.save # automatically creates derivatives on promotion
|
581
577
|
```
|
582
578
|
|
583
579
|
You can then retrieve the URL of a processed derivative:
|
@@ -711,7 +707,7 @@ photo/
|
|
711
707
|
...
|
712
708
|
```
|
713
709
|
|
714
|
-
|
710
|
+
But you can also override `Shrine#generate_location` with a custom
|
715
711
|
implementation, for example:
|
716
712
|
|
717
713
|
```rb
|
@@ -903,7 +899,7 @@ resumable uploads from scratch, it includes a complete JavaScript example
|
|
903
899
|
|
904
900
|
## Backgrounding
|
905
901
|
|
906
|
-
The [`backgrounding`][backgrounding plugin] allows you to move file promotion
|
902
|
+
The [`backgrounding`][backgrounding plugin] plugin allows you to move file promotion
|
907
903
|
and deletion into a background job, using the backgrounding library [of your
|
908
904
|
choice][Backgrounding Libraries]:
|
909
905
|
|
data/doc/multiple_files.md
CHANGED
@@ -228,7 +228,7 @@ photos_attributes = album_params[:photos_attributes].to_h.merge(new_photos_attri
|
|
228
228
|
album_attributes = album_params.merge(photos_attributes: photos_attributes)
|
229
229
|
|
230
230
|
# create the album with photos
|
231
|
-
Album.create(
|
231
|
+
Album.create(album_attributes)
|
232
232
|
```
|
233
233
|
|
234
234
|
In this case you need to make sure your form tag has
|
data/doc/paperclip.md
CHANGED
@@ -358,13 +358,14 @@ module PaperclipShrineSynchronization
|
|
358
358
|
end
|
359
359
|
end
|
360
360
|
|
361
|
-
# If you'll be using a `:prefix` on your Shrine storage, or you're storing
|
362
|
-
# files on the filesystem, make sure to subtract the appropriate part
|
363
|
-
# from the path assigned to `:id`.
|
364
361
|
def shrine_attachment_file(attachment)
|
362
|
+
location = attachment.path
|
363
|
+
# if you're storing files on disk, make sure to subtract the absolute path
|
364
|
+
location = location.sub(%r{^#{storage.prefix}/}, "") if storage.prefix
|
365
|
+
|
365
366
|
Shrine.uploaded_file(
|
366
367
|
storage: :store,
|
367
|
-
id:
|
368
|
+
id: location,
|
368
369
|
metadata: {
|
369
370
|
"size" => attachment.size,
|
370
371
|
"filename" => attachment.original_filename,
|
@@ -377,12 +378,20 @@ module PaperclipShrineSynchronization
|
|
377
378
|
# files on the filesystem, make sure to subtract the appropriate part
|
378
379
|
# from the path assigned to `:id`.
|
379
380
|
def shrine_style_file(style)
|
381
|
+
location = style.attachment.path(style.name)
|
382
|
+
# if you're storing files on disk, make sure to subtract the absolute path
|
383
|
+
location = location.sub(%r{^#{storage.prefix}/}, "") if storage.prefix
|
384
|
+
|
380
385
|
Shrine.uploaded_file(
|
381
386
|
storage: :store,
|
382
|
-
id:
|
387
|
+
id: location,
|
383
388
|
metadata: {},
|
384
389
|
)
|
385
390
|
end
|
391
|
+
|
392
|
+
def storage
|
393
|
+
Shrine.storages[:store]
|
394
|
+
end
|
386
395
|
end
|
387
396
|
```
|
388
397
|
```rb
|
data/doc/plugins/add_metadata.md
CHANGED
@@ -34,6 +34,26 @@ uploaded_file.metadata["page_count"] #=> 30
|
|
34
34
|
uploaded_file.page_count #=> 30
|
35
35
|
```
|
36
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
|
55
|
+
```
|
56
|
+
|
37
57
|
### Multiple values
|
38
58
|
|
39
59
|
You can also extract multiple metadata values at once, by using `add_metadata`
|
@@ -3,14 +3,48 @@ title: Atomic Helpers
|
|
3
3
|
---
|
4
4
|
|
5
5
|
The [`atomic_helpers`][atomic_helpers] plugin provides API for retrieving and
|
6
|
-
persisting attachments in a concurrency-safe way, which is useful
|
7
|
-
the `backgrounding` plugin. The database plugins (`activerecord`
|
8
|
-
implement atomic promotion and atomic persistence on top of this
|
6
|
+
persisting attachments in a concurrency-safe way, which is especially useful
|
7
|
+
when using the `backgrounding` plugin. The database plugins (`activerecord`
|
8
|
+
and `sequel`) implement atomic promotion and atomic persistence on top of this
|
9
|
+
plugin.
|
9
10
|
|
10
11
|
```rb
|
11
12
|
plugin :atomic_helpers
|
12
13
|
```
|
13
14
|
|
15
|
+
## Problem Statement
|
16
|
+
|
17
|
+
What happens if two different processors (web workers, background jobs,
|
18
|
+
command-line executions, whatever) try to edit a shrine attachment
|
19
|
+
concurrently? The kinds of edits typically made include: "promoting a file",
|
20
|
+
moving it to a different storage and persisting that change in the model;
|
21
|
+
adding or changing a derivative; adding or changing a metadata element.
|
22
|
+
|
23
|
+
There are two main categories of "race condition":
|
24
|
+
|
25
|
+
1. The file could be switched out from under you. If you were promoting a file,
|
26
|
+
but some other process has *changed* the attachment, you don't want to
|
27
|
+
overwrite it with the promomoted version of the *prior* attacchment. Likewise,
|
28
|
+
if you were adding metadata or a derivative, they would be corresponding to a
|
29
|
+
certain attachment, and you don't want to accidentally add them to a now changed
|
30
|
+
attacchment for which they are inappropriate.
|
31
|
+
|
32
|
+
2. Overwriting each other's edits. Since all shrine (meta)data is stored in a
|
33
|
+
single JSON hash, standard implementations will write the entire JSON hash at
|
34
|
+
once to a rdbms column or other store. If two processes both read in the hash,
|
35
|
+
make a change to different keys in it, and then write it back out, the second
|
36
|
+
process to write will 'win' and overwrite changes made by the first.
|
37
|
+
|
38
|
+
The atomic helpers give you tools to avoid both of these sorts of race
|
39
|
+
conditions, under conditions of concurrent editing.
|
40
|
+
|
41
|
+
## High-level ORM helpers
|
42
|
+
|
43
|
+
If you are using the `sequel` or `activerecord` plugins, they give you two
|
44
|
+
higher-level helpers: `atomic_persist` and `atomic_promote`. See the
|
45
|
+
[persistence] documentation for more.
|
46
|
+
|
47
|
+
|
14
48
|
## Retrieving
|
15
49
|
|
16
50
|
The `Attacher.retrieve` method provided by the plugin instantiates an attacher
|
@@ -177,3 +211,7 @@ end
|
|
177
211
|
```
|
178
212
|
|
179
213
|
[atomic_helpers]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/atomic_helpers.rb
|
214
|
+
|
215
|
+
[persistence]: https://shrinerb.com/docs/plugins/persistence
|
216
|
+
|
217
|
+
[backgrounding]: https://shrinerb.com/docs/plugins/backgrounding
|
data/doc/plugins/derivatives.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
title: Derivatives
|
3
3
|
---
|
4
4
|
|
5
|
-
The derivatives plugin allows storing processed files ("derivatives") alongside
|
5
|
+
The [`derivatives`][derivatives] plugin allows storing processed files ("derivatives") alongside
|
6
6
|
the main attached file. The processed file data will be saved together with the
|
7
7
|
main attachment data in the same record attribute.
|
8
8
|
|
@@ -38,17 +38,9 @@ class ImageUploader < Shrine
|
|
38
38
|
end
|
39
39
|
```
|
40
40
|
```rb
|
41
|
-
class Photo < Model(:image_data)
|
42
|
-
include ImageUploader::Attachment(:image)
|
43
|
-
end
|
44
|
-
```
|
45
|
-
```rb
|
46
41
|
photo = Photo.new(image: file)
|
47
|
-
|
48
|
-
|
49
|
-
photo.image_derivatives! if photo.image_changed? # create derivatives
|
50
|
-
photo.save
|
51
|
-
end
|
42
|
+
photo.image_derivatives! # creates derivatives
|
43
|
+
photo.save
|
52
44
|
```
|
53
45
|
|
54
46
|
You can then retrieve the URL of a processed derivative:
|
@@ -205,6 +197,19 @@ attacher.create_derivatives(different_source) # pass a different source file
|
|
205
197
|
attacher.create_derivatives(foo: "bar") # pass custom options to the processor
|
206
198
|
```
|
207
199
|
|
200
|
+
### Create on promote
|
201
|
+
|
202
|
+
You can also have derivatives created automatically on promotion:
|
203
|
+
|
204
|
+
```rb
|
205
|
+
Shrine.plugin :derivatives, create_on_promote: true
|
206
|
+
```
|
207
|
+
```rb
|
208
|
+
attacher.assign(file)
|
209
|
+
attacher.finalize # creates derivatives on promotion
|
210
|
+
attacher.derivatives #=> { small: ..., medium: ..., large: ... }
|
211
|
+
```
|
212
|
+
|
208
213
|
### Naming processors
|
209
214
|
|
210
215
|
If you want to have multiple processors for an uploader, you can assign each
|
@@ -396,7 +401,8 @@ attacher.process_derivatives(:my_processor) # downloads attached file and passes
|
|
396
401
|
|
397
402
|
If you want to use a different source file, you can pass it in to the process
|
398
403
|
call. Typically you'd pass a local file on disk. If you pass a
|
399
|
-
`Shrine::UploadedFile` object, it will be
|
404
|
+
`Shrine::UploadedFile` object or another IO-like object, it will be
|
405
|
+
automatically downloaded/copied to a local TempFile on disk.
|
400
406
|
|
401
407
|
```rb
|
402
408
|
# named processor:
|
@@ -416,6 +422,20 @@ attacher.file.download do |original|
|
|
416
422
|
end
|
417
423
|
```
|
418
424
|
|
425
|
+
If a processor might not always need a local source file, you avoid a
|
426
|
+
potentially expensive download/copy by registering the processor with
|
427
|
+
`download: false`, in which case the source file will be passed to the
|
428
|
+
processor as is.
|
429
|
+
|
430
|
+
```rb
|
431
|
+
Attacher.derivatives :my_processor, download: false do |source|
|
432
|
+
source #=> Could be File, Shrine::UploadedFile, or other IO-like object
|
433
|
+
shrine_class.with_file(source) do |file|
|
434
|
+
# can force download/copy if necessary with `with_file`,
|
435
|
+
end
|
436
|
+
end
|
437
|
+
```
|
438
|
+
|
419
439
|
## Adding derivatives
|
420
440
|
|
421
441
|
If you already have processed files that you want to save, you can do that with
|
@@ -459,6 +479,11 @@ For adding a single derivative, you can also use the singular
|
|
459
479
|
attacher.add_derivative(:thumb, thumbnail_file)
|
460
480
|
```
|
461
481
|
|
482
|
+
> Note that new derivatives will replace any existing derivatives living under
|
483
|
+
the same key, but won't delete them. If this is your case, make sure to save a
|
484
|
+
reference to the old derivatives before assigning new ones, and then delete
|
485
|
+
them after persisting the change.
|
486
|
+
|
462
487
|
Any options passed to `Attacher#add_derivative(s)` will be forwarded to
|
463
488
|
[`Attacher#upload_derivatives`](#uploading-derivatives).
|
464
489
|
|
@@ -567,6 +592,11 @@ attacher.merge_derivatives attacher.upload_derivatives({ nested: { two: two_file
|
|
567
592
|
attacher.derivatives #=> { nested: { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> } }
|
568
593
|
```
|
569
594
|
|
595
|
+
> Note that new derivatives will replace any existing derivatives living under
|
596
|
+
the same key, but won't delete them. If this is your case, make sure to save a
|
597
|
+
reference to the old derivatives before assigning new ones, and then delete
|
598
|
+
them after persisting the change.
|
599
|
+
|
570
600
|
The `Attacher#merge_derivatives` method is thread-safe.
|
571
601
|
|
572
602
|
### Setting derivatives
|
@@ -793,6 +823,7 @@ Or disable logging altogether:
|
|
793
823
|
plugin :derivatives, log_subscriber: nil
|
794
824
|
```
|
795
825
|
|
826
|
+
[derivatives]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/derivatives.rb
|
796
827
|
[default_url]: https://shrinerb.com/docs/plugins/default_url
|
797
828
|
[entity]: https://shrinerb.com/docs/plugins/entity
|
798
829
|
[model]: https://shrinerb.com/docs/plugins/model
|