shrine 3.0.0.beta2 → 3.0.0.beta3

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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +45 -1
  3. data/README.md +100 -106
  4. data/doc/advantages.md +90 -88
  5. data/doc/attacher.md +322 -152
  6. data/doc/carrierwave.md +105 -113
  7. data/doc/changing_derivatives.md +308 -0
  8. data/doc/changing_location.md +92 -21
  9. data/doc/changing_storage.md +107 -0
  10. data/doc/creating_plugins.md +1 -1
  11. data/doc/design.md +8 -9
  12. data/doc/direct_s3.md +3 -2
  13. data/doc/metadata.md +97 -78
  14. data/doc/multiple_files.md +3 -3
  15. data/doc/paperclip.md +89 -88
  16. data/doc/plugins/activerecord.md +3 -12
  17. data/doc/plugins/backgrounding.md +126 -100
  18. data/doc/plugins/derivation_endpoint.md +4 -5
  19. data/doc/plugins/derivatives.md +63 -32
  20. data/doc/plugins/download_endpoint.md +54 -1
  21. data/doc/plugins/entity.md +1 -0
  22. data/doc/plugins/form_assign.md +53 -0
  23. data/doc/plugins/mirroring.md +37 -16
  24. data/doc/plugins/multi_cache.md +22 -0
  25. data/doc/plugins/presign_endpoint.md +1 -1
  26. data/doc/plugins/remote_url.md +19 -4
  27. data/doc/plugins/validation.md +83 -0
  28. data/doc/processing.md +149 -133
  29. data/doc/refile.md +68 -63
  30. data/doc/release_notes/3.0.0.md +835 -0
  31. data/doc/securing_uploads.md +56 -36
  32. data/doc/storage/s3.md +2 -2
  33. data/doc/testing.md +104 -120
  34. data/doc/upgrading_to_3.md +538 -0
  35. data/doc/validation.md +48 -87
  36. data/lib/shrine.rb +7 -4
  37. data/lib/shrine/attacher.rb +16 -6
  38. data/lib/shrine/plugins/activerecord.rb +33 -14
  39. data/lib/shrine/plugins/atomic_helpers.rb +1 -1
  40. data/lib/shrine/plugins/backgrounding.rb +23 -89
  41. data/lib/shrine/plugins/data_uri.rb +13 -2
  42. data/lib/shrine/plugins/derivation_endpoint.rb +7 -11
  43. data/lib/shrine/plugins/derivatives.rb +44 -20
  44. data/lib/shrine/plugins/download_endpoint.rb +26 -0
  45. data/lib/shrine/plugins/form_assign.rb +6 -3
  46. data/lib/shrine/plugins/keep_files.rb +2 -2
  47. data/lib/shrine/plugins/mirroring.rb +62 -22
  48. data/lib/shrine/plugins/model.rb +2 -2
  49. data/lib/shrine/plugins/multi_cache.rb +27 -0
  50. data/lib/shrine/plugins/remote_url.rb +25 -10
  51. data/lib/shrine/plugins/remove_invalid.rb +1 -1
  52. data/lib/shrine/plugins/sequel.rb +39 -20
  53. data/lib/shrine/plugins/validation.rb +3 -0
  54. data/lib/shrine/storage/s3.rb +16 -1
  55. data/lib/shrine/uploaded_file.rb +1 -0
  56. data/lib/shrine/version.rb +1 -1
  57. data/shrine.gemspec +1 -1
  58. metadata +12 -7
  59. data/doc/migrating_storage.md +0 -76
  60. data/doc/regenerating_versions.md +0 -143
  61. data/lib/shrine/plugins/attacher_options.rb +0 -55
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e35bbe08c0a54aca90746357823eea8bd7f65f7ee64a988fe6bc9c3931f70a91
4
- data.tar.gz: 1c70a7212c59f13fa435b866d0dad8c81989d7ee41722247d5107edec461047b
3
+ metadata.gz: ad93860597c6a720f0159063d8cbb95a6aa0e93ea89947803342500f1193eb64
4
+ data.tar.gz: 79801e74ecd993986099f0f4679fcb37c2b778157c4df5bf6bb80064f2338a44
5
5
  SHA512:
6
- metadata.gz: 784c4f79052ef3132ffe26544a79de6f27e9209563cd9c08d475a3e52e0b7b201041f516caebc00315f802c1c9d18e7bd74b0e8e5977576727dccfefe47d0c3b
7
- data.tar.gz: 6788e1946a1062a3f184b87cf016b7104d6c524621853fb38a8c092d245fa244625a16866dde958bf53caa4bbb113b6d0e01fb09c7340b39633360e40b5d4ee4
6
+ metadata.gz: 12337c687f57272f9af85b8b8831de448fea258e25e6b7191b95131a60e705374807a87efb7c5e4e7c3db0c6f11a8c3dc87dfe21255d24785e908a93cc94be7e
7
+ data.tar.gz: 04561d887c0612ed193c31c470fcdd9ca5ed466794923ceecf979f78049ec3c9c46cf0161776121c72419bcc5f77babfc565ceaf6892a06a547bd93f9c1cccce
@@ -1,3 +1,45 @@
1
+ ## 3.0.0.beta3 (2019-09-25)
2
+
3
+ * `multi_cache` – Add new plugin for whitelisting additional temporary storages (@janko, @jrochkind)
4
+
5
+ * `s3` – Allow uploading files larger than 50 GB (@janko)
6
+
7
+ * `sequel` – Extract callback code into attacher methods that can be overridden (@janko)
8
+
9
+ * `activerecord` – Extract callback code into attacher methods that can be overridden (@janko)
10
+
11
+ * `derivatives` – Ensure binary mode for `File` and `Tempfile` objects (@janko)
12
+
13
+ * `derivatives` – Ensure refreshed file descriptor for `Tempfile` objects (@janko)
14
+
15
+ * `derivation_endpoint` – Stop re-opening `File` objects returned in derivation result (@janko)
16
+
17
+ * `derivation_endpoint` – Allow only `File` or `Tempfile` object as derivation result (@janko)
18
+
19
+ * `derivatives` – Add support for default processors (@janko)
20
+
21
+ * `remote_url` – Convert only `Down::Error` and `DownloadError` exceptions into validation errors (@janko)
22
+
23
+ * `remote_url` – Bring back `Attacher#remote_url=` and `Attacher#remote_url` (@janko)
24
+
25
+ * `data_uri` – Bring back `Attacher#data_uri=` and `Attacher#data_uri` (@janko)
26
+
27
+ * `mirroring` – Allow skipping mirroring by passing `mirror: false` to `#upload` and `#delete` (@janko)
28
+
29
+ * `mirroring` – Rename `Shrine.mirror_(upload|delete)` to `Shrine.mirror_(upload|delete)_block` (@janko)
30
+
31
+ * `mirroring` – Add `UploadedFile#mirror_(upload|delete)_background` (@janko)
32
+
33
+ * `attacher_options` – Remove plugin (@janko)
34
+
35
+ * `backgrounding` – Move `Attacher#destroy(background: true)` to `Attacher#destroy_background` (@janko)
36
+
37
+ * `backgrounding` – Move `Attacher#promote(background: true)` to `Attacher#promote_background` (@janko)
38
+
39
+ * `download_endpoint` – Add `Shrine.download_response` for calling in controller (@janko)
40
+
41
+ * `core` – Fetch storage object lazily in `Shrine` instance (@janko)
42
+
1
43
  ## 3.0.0.beta2 (2019-09-11)
2
44
 
3
45
  * `column` – Allow `Attacher#load_column` to receive a hash (@janko)
@@ -154,7 +196,7 @@
154
196
 
155
197
  * `upload_endpoint` – Stop passing `Rack::Request` object to the uploader (@janko)
156
198
 
157
- * `remote_url` – Require custom downlodaers to raise `Shrine::Plugins::RemoteUrl::DownloadError` for conversion into a validation error (@janko)
199
+ * `remote_url` – Require custom downloaders to raise `Shrine::Plugins::RemoteUrl::DownloadError` for conversion into a validation error (@janko)
158
200
 
159
201
  * `remote_url` – Remove `Attacher#remote_url=` and `Attacher#remote_url` (@janko)
160
202
 
@@ -262,6 +304,8 @@
262
304
 
263
305
  * `hooks` – Remove plugin (@janko)
264
306
 
307
+ * `core` – Remove deprecated `Shrine::IO_METHODS` constant (@janko)
308
+
265
309
  * `s3` – Replace source object metadata when copying a file from S3 (@janko)
266
310
 
267
311
  * `core` – Change `UploadedFile#storage_key` to return a Symbol instead of a String (@janko)
data/README.md CHANGED
@@ -5,8 +5,8 @@ Shrine is a toolkit for file attachments in Ruby applications. Some highlights:
5
5
  * **Modular design** – the [plugin system] allows you to load only the functionality you need
6
6
  * **Memory friendly** – streaming uploads and [downloads][Retrieving Uploads] make it work great with large files
7
7
  * **Cloud storage** – store files on [disk][FileSystem], [AWS S3][S3], [Google Cloud][GCS], [Cloudinary] and [others][external]
8
- * **ORM integrations** – works with [Sequel][sequel plugin], [ActiveRecord][activerecord plugin], [Hanami::Model][hanami plugin] and [Mongoid][mongoid plugin]
9
- * **Flexible processing** – generate thumbnails [on upload] or [on-the-fly] using [ImageMagick][ImageProcessing::MiniMagick] or [libvips][ImageProcessing::Vips]
8
+ * **Persistence integrations** – works with [Sequel][sequel plugin], [ActiveRecord][activerecord plugin], [ROM][rom plugin], [Hanami::Model][hanami plugin] and [Mongoid][mongoid plugin]
9
+ * **Flexible processing** – generate thumbnails [up front] or [on-the-fly] using [ImageMagick][ImageProcessing::MiniMagick] or [libvips][ImageProcessing::Vips]
10
10
  * **Metadata validation** – [validate files][validation] based on [extracted metadata][metadata]
11
11
  * **Direct uploads** – upload asynchronously [to your app][simple upload] or [to the cloud][presigned upload] using [Uppy]
12
12
  * **Resumable uploads** – make large file uploads [resumable][resumable upload] on [S3][uppy-s3_multipart] or [tus][tus-ruby-server]
@@ -16,14 +16,14 @@ If you're curious how it compares to other file attachment libraries, see the [A
16
16
 
17
17
  ## Resources
18
18
 
19
- | Resource | URL |
20
- | :---------------- | :----------------------------------------------------------------------------------------- |
21
- | Website | [shrinerb.com](https://shrinerb.com) |
22
- | Demo code | [Roda][roda demo] / [Rails][rails demo] |
23
- | Source | [github.com/shrinerb/shrine](https://github.com/shrinerb/shrine) |
24
- | Wiki | [github.com/shrinerb/shrine/wiki](https://github.com/shrinerb/shrine/wiki) |
25
- | Bugs | [github.com/shrinerb/shrine/issues](https://github.com/shrinerb/shrine/issues) |
26
- | Help & Discussion | [groups.google.com/group/ruby-shrine](https://groups.google.com/forum/#!forum/ruby-shrine) |
19
+ | Resource | URL |
20
+ | :---------------- | :----------------------------------------------------------------------------- |
21
+ | Website | [shrinerb.com](https://shrinerb.com) |
22
+ | Demo code | [Roda][roda demo] / [Rails][rails demo] |
23
+ | Source | [github.com/shrinerb/shrine](https://github.com/shrinerb/shrine) |
24
+ | Wiki | [github.com/shrinerb/shrine/wiki](https://github.com/shrinerb/shrine/wiki) |
25
+ | Bugs | [github.com/shrinerb/shrine/issues](https://github.com/shrinerb/shrine/issues) |
26
+ | Help & Discussion | [discourse.shrinerb.com](https://discourse.shrinerb.com) |
27
27
 
28
28
  ## Contents
29
29
 
@@ -40,7 +40,7 @@ If you're curious how it compares to other file attachment libraries, see the [A
40
40
  * [MIME type](#mime-type)
41
41
  * [Other metadata](#other-metadata)
42
42
  * [Processing](#processing)
43
- * [Processing on upload](#processing-on-upload)
43
+ * [Processing up front](#processing-up-front)
44
44
  * [Processing on-the-fly](#processing-on-the-fly)
45
45
  * [Validation](#validation)
46
46
  * [Location](#location)
@@ -84,7 +84,7 @@ will use to store all information about the attachment:
84
84
  ```rb
85
85
  Sequel.migration do
86
86
  change do
87
- add_column :photos, :image_data, :text
87
+ add_column :photos, :image_data, :text # or :jsonb
88
88
  end
89
89
  end
90
90
  ```
@@ -97,7 +97,7 @@ $ rails generate migration add_image_data_to_photos image_data:text
97
97
  ```rb
98
98
  class AddImageDataToPhotos < ActiveRecord::Migration
99
99
  def change
100
- add_column :photos, :image_data, :text
100
+ add_column :photos, :image_data, :text # or :jsonb
101
101
  end
102
102
  end
103
103
  ```
@@ -115,14 +115,14 @@ end
115
115
 
116
116
  ```rb
117
117
  class Photo < Sequel::Model # ActiveRecord::Base
118
- include ImageUploader::Attachment.new(:image) # adds an `image` virtual attribute
118
+ include ImageUploader::Attachment(:image) # adds an `image` virtual attribute
119
119
  end
120
120
  ```
121
121
 
122
- Let's now add the form fields which will use this virtual attribute (which is
123
- `image`, NOT `image_data`). We need (1) a file field for choosing files, and
124
- (2) a hidden field for retaining the uploaded file in case of validation errors
125
- and for potential [direct uploads].
122
+ Let's now add the form fields which will use this virtual attribute (NOT the
123
+ `<attachment>_data` column attribute). We need (1) a file field for choosing
124
+ files, and (2) a hidden field for retaining the uploaded file in case of
125
+ validation errors and for potential [direct uploads].
126
126
 
127
127
  ```rb
128
128
  # with Rails form builder:
@@ -251,7 +251,7 @@ organize them in any way you like.
251
251
 
252
252
  ### Uploading
253
253
 
254
- The main method of the uploader is `#upload`, which takes an [IO-like
254
+ The main method of the uploader is `Shrine.upload`, which takes an [IO-like
255
255
  object][io abstraction] and a storage identifier on the input, and returns a
256
256
  representation of the [uploaded file] on the output.
257
257
 
@@ -259,8 +259,8 @@ representation of the [uploaded file] on the output.
259
259
  MyUploader.upload(file, :store) #=> #<Shrine::UploadedFile>
260
260
  ```
261
261
 
262
- Internally this instantiates the uploader with the storage and calls `#upload`
263
- on it:
262
+ Internally this instantiates the uploader with the storage and calls
263
+ `Shrine#upload`:
264
264
 
265
265
  ```rb
266
266
  uploader = MyUploader.new(:store)
@@ -269,13 +269,12 @@ uploader.upload(file) #=> #<Shrine::UploadedFile>
269
269
 
270
270
  Some of the tasks performed by `#upload` include:
271
271
 
272
- * any defined [file processing][on upload]
273
272
  * extracting [metadata]
274
273
  * generating [location]
275
274
  * uploading (this is where the [storage] is called)
276
275
  * closing the uploaded file
277
276
 
278
- The second argument is a `context` hash which is forwarded to places like
277
+ The second argument is a "context" hash which is forwarded to places like
279
278
  metadata extraction and location generation, but it has a few special options:
280
279
 
281
280
  ```rb
@@ -434,10 +433,10 @@ photo.image_attacher #=> #<Shrine::Attacher>
434
433
  The `Shrine::Attacher` object can be instantiated and used directly:
435
434
 
436
435
  ```rb
437
- attacher = ImageUploader::Attacher.new(photo, :image)
436
+ attacher = ImageUploader::Attacher.from_model(photo, :image)
438
437
 
439
438
  attacher.assign(file) # equivalent to `photo.image = file`
440
- attacher.get # equivalent to `photo.image`
439
+ attacher.file # equivalent to `photo.image`
441
440
  attacher.url # equivalent to `photo.image_url`
442
441
  ```
443
442
 
@@ -521,79 +520,72 @@ the [Extracting Metadata] guide for more details.
521
520
 
522
521
  ## Processing
523
522
 
524
- Shrine allows you to process attached files either "on upload" or
525
- "on-the-fly". For example, if your app is accepting image uploads, you can
526
- generate a pre-defined set of of thumbnails as soon as the image is attached to
527
- a record ("on upload"), or you can generate necessary thumbnails dynamically as
528
- they're needed ("on-the-fly").
523
+ Shrine allows you to process attached files up front or on-the-fly. For
524
+ example, if your app is accepting image uploads, you can generate a predefined
525
+ set of of thumbnails when the image is attached to a record, or you can have
526
+ thumbnails generated dynamically as they're needed.
529
527
 
530
- For image processing it's recommended to use the **[ImageProcessing]** gem,
528
+ For image processing, it's recommended to use the **[ImageProcessing]** gem,
531
529
  which is a high-level wrapper for processing with [ImageMagick] (via
532
530
  [MiniMagick]) or [libvips] (via [ruby-vips]).
533
531
 
534
- ### Processing on upload
535
-
536
- For processing "on upload", you can intercept when a cached file is being
537
- uploaded to permanent storage, and perform any file processing you might want.
538
- The [`processing`][processing plugin] plugin provides the promotion hook, while
539
- the [`versions`][versions plugin] plugin enables handling a hash of versions.
540
-
541
532
  ```sh
542
- $ brew install imagemagick
533
+ $ brew install imagemagick vips
543
534
  ```
535
+
536
+ ### Processing up front
537
+
538
+ You can use the [`derivatives`][derivatives plugin] plugin to generate a set of
539
+ pre-defined processed files:
540
+
544
541
  ```rb
545
542
  # Gemfile
546
- gem "image_processing", "~> 1.2"
543
+ gem "image_processing", "~> 1.8"
544
+ ```
545
+ ```rb
546
+ Shrine.plugin :derivatives
547
547
  ```
548
548
  ```rb
549
549
  require "image_processing/mini_magick"
550
550
 
551
551
  class ImageUploader < Shrine
552
- plugin :processing # allows hooking into promoting
553
- plugin :versions # enable Shrine to handle a hash of files
554
- plugin :delete_raw # delete processed files after uploading
555
-
556
- process(:store) do |io, context|
557
- versions = { original: io } # retain original
558
-
559
- io.download do |original|
560
- pipeline = ImageProcessing::MiniMagick.source(original)
561
-
562
- versions[:large] = pipeline.resize_to_limit!(800, 800)
563
- versions[:medium] = pipeline.resize_to_limit!(500, 500)
564
- versions[:small] = pipeline.resize_to_limit!(300, 300)
565
- end
566
-
567
- versions # return the hash of processed files
552
+ Attacher.derivatives_processor do |original|
553
+ magick = ImageProcessing::MiniMagick.source(original)
554
+
555
+ {
556
+ large: magick.resize_to_limit!(800, 800),
557
+ medium: magick.resize_to_limit!(500, 500),
558
+ small: magick.resize_to_limit!(300, 300),
559
+ }
568
560
  end
569
561
  end
570
562
  ```
563
+ ```rb
564
+ photo = Photo.new(image: file)
565
+ photo.image_derivatives! # calls derivatives processor and uploads results
566
+ photo.save
567
+ ```
571
568
 
572
- After the files are uploaded, their data is saved into the `<attachment>_data`
573
- column, and the attachment getter will read them as a Hash of
574
- [`Shrine::UploadedFile`][uploaded file] objects.
569
+ If you're allowing the attached file to be updated later on, in your update
570
+ route make sure to create derivatives for new attachments:
575
571
 
576
572
  ```rb
577
- photo = Photo.create(image: file) # processing is triggered
578
- photo.image #=>
579
- # {
580
- # :original => #<Shrine::UploadedFile @data={"id"=>"9sd84.jpg", ...}>,
581
- # :large => #<Shrine::UploadedFile @data={"id"=>"lg043.jpg", ...}>,
582
- # :medium => #<Shrine::UploadedFile @data={"id"=>"kd9fk.jpg", ...}>,
583
- # :small => #<Shrine::UploadedFile @data={"id"=>"932fl.jpg", ...}>,
584
- # }
573
+ photo.image_derivatives! if photo.image_changed?
574
+ ```
585
575
 
586
- photo.image[:medium] #=> #<Shrine::UploadedFile>
587
- photo.image[:medium].url #=> "/uploads/store/lg043.jpg"
588
- photo.image[:medium].size #=> 5825949
589
- photo.image[:medium].mime_type #=> "image/jpeg"
576
+ After the processed files are uploaded, their data is saved into the
577
+ `<attachment>_data` column. You can then retrieve the derivatives as
578
+ [`Shrine::UploadedFile`][uploaded file] objects:
590
579
 
591
- photo.image_url(:large) # returns version URL with fallbacks in case version is missing
580
+ ```rb
581
+ photo.image(:large) #=> #<Shrine::UploadedFile ...>
582
+ photo.image(:large).url #=> "/uploads/store/lg043.jpg"
583
+ photo.image(:large).size #=> 5825949
584
+ photo.image(:large).mime_type #=> "image/jpeg"
592
585
  ```
593
586
 
594
- By default processing is executed synchronously, but you can choose to delay it
595
- into a [background job][backgrounding]. You can also do any other type of file
596
- processing you want, see the [File Processing] guide for more details.
587
+ For more details, see the [`derivatives`][derivatives plugin] plugin
588
+ documentation and the [File Processing] guide.
597
589
 
598
590
  ### Processing on-the-fly
599
591
 
@@ -606,12 +598,9 @@ To set it up, we mount the Rack app in our router on a chosen path prefix,
606
598
  configure the plugin with a secret key and that path prefix, and define
607
599
  processing we want to perform:
608
600
 
609
- ```sh
610
- $ brew install imagemagick
611
- ```
612
601
  ```rb
613
602
  # Gemfile
614
- gem "image_processing", "~> 1.2"
603
+ gem "image_processing", "~> 1.8"
615
604
  ```
616
605
  ```rb
617
606
  # config/routes.rb (Rails)
@@ -650,17 +639,19 @@ more details.
650
639
 
651
640
  ## Validation
652
641
 
653
- Shrine can perform file validations for files assigned to the model, with
654
- [`validation_helpers`][validation_helpers plugin] plugin providing some common
655
- validation methods:
642
+ The [`validation`][validation plugin] plugin allows performing validation for
643
+ attached files. For common validations, the
644
+ [`validation_helpers`][validation_helpers plugin] plugin provides useful
645
+ validators for built in metadata:
656
646
 
647
+ ```rb
648
+ Shrine.plugin :validation_helpers
649
+ ```
657
650
  ```rb
658
651
  class DocumentUploader < Shrine
659
- plugin :validation_helpers
660
-
661
652
  Attacher.validate do
662
653
  validate_max_size 5*1024*1024, message: "is too large (max is 5 MB)"
663
- validate_mime_type_inclusion %w[application/pdf]
654
+ validate_mime_type %w[application/pdf]
664
655
  end
665
656
  end
666
657
  ```
@@ -685,9 +676,9 @@ plugin provides a good default hierarchy, but you can also override
685
676
 
686
677
  ```rb
687
678
  class ImageUploader < Shrine
688
- def generate_location(io, context)
689
- type = context[:record].class.name.downcase if context[:record]
690
- style = context[:version] == :original ? "originals" : "thumbs" if context[:version]
679
+ def generate_location(io, record: nil, derivative: nil, **)
680
+ type = record.class.name.downcase if record
681
+ style = derivative ? "thumbs" : "originals"
691
682
  name = super # the default unique identifier
692
683
 
693
684
  [type, style, name].compact.join("/")
@@ -706,7 +697,7 @@ uploads/
706
697
 
707
698
  Note that there should always be a random component in the location, so that
708
699
  the ORM dirty tracking is detected properly. Inside `#generate_location` you
709
- can also access the extracted metadata through `context[:metadata]`.
700
+ can also access the extracted metadata through the `:metadata` option.
710
701
 
711
702
  ## Direct uploads
712
703
 
@@ -851,29 +842,30 @@ resumable uploads from scratch, it includes a complete JavaScript example
851
842
 
852
843
  ## Backgrounding
853
844
 
854
- Shrine allows you to put file deletion and promotion of cached files to
855
- permanent storage into a background job. The [`backgrounding`][backgrounding
856
- plugin] plugin provides hooks for plugging in your [favourite backgrounding
857
- library][Backgrounding Libraries].
845
+ The [`backgrounding`][backgrounding plugin] allows you to move file promotion
846
+ and deletion into a background job, using the backgrounding library [of your
847
+ choice][Backgrounding Libraries]:
858
848
 
859
849
  ```rb
860
850
  Shrine.plugin :backgrounding
861
- Shrine::Attacher.promote { |data| PromoteJob.perform_async(data) }
862
- Shrine::Attacher.delete { |data| DeleteJob.perform_async(data) }
851
+ Shrine::Attacher.promote_block { PromoteJob.perform_later(self.class, record, name, file_data) }
852
+ Shrine::Attacher.destroy_block { DestroyJob.perform_later(self.class, data) }
863
853
  ```
864
854
  ```rb
865
- class PromoteJob
866
- include Sidekiq::Worker
867
- def perform(data)
868
- Shrine::Attacher.promote(data)
855
+ class PromoteJob < ActiveJob::Base
856
+ def perform(attacher_class, record, name, file_data)
857
+ attacher = attacher_class.retrieve(model: record, name: name, file: file_data)
858
+ attacher.atomic_promote
859
+ rescue Shrine::AttachmentChanged, ActiveRecord::RecordNotFound
860
+ # attachment has changed or the record has been deleted, nothing to do
869
861
  end
870
862
  end
871
863
  ```
872
864
  ```rb
873
- class DeleteJob
874
- include Sidekiq::Worker
875
- def perform(data)
876
- Shrine::Attacher.delete(data)
865
+ class DestroyJob < ActiveJob::Base
866
+ def perform(attacher_class, data)
867
+ attacher = attacher_class.from_data(data)
868
+ attacher.destroy
877
869
  end
878
870
  end
879
871
  ```
@@ -926,6 +918,7 @@ Some plugins add their own instrumentation as well when they detect that the
926
918
  | Plugin | Instrumentation |
927
919
  | :----- | :-------------- |
928
920
  | `derivation_endpoint` | instruments file processing |
921
+ | `derivatives` | instruments file processing |
929
922
  | `determine_mime_type` | instruments analyzing MIME type |
930
923
  | `store_dimensions` | instruments extracting image dimensions |
931
924
  | `signature` | instruments calculating signature |
@@ -993,7 +986,7 @@ The gem is available as open source under the terms of the [MIT License].
993
986
  [io abstraction]: #io-abstraction
994
987
  [location]: #location
995
988
  [metadata]: #metadata
996
- [on upload]: #processing-on-upload
989
+ [up front]: #processing-up-front
997
990
  [on-the-fly]: #processing-on-the-fly
998
991
  [plugin system]: #plugin-system
999
992
  [simple upload]: #simple-direct-upload
@@ -1045,20 +1038,21 @@ The gem is available as open source under the terms of the [MIT License].
1045
1038
  [add_metadata plugin]: /doc/plugins/add_metadata.md#readme
1046
1039
  [backgrounding plugin]: /doc/plugins/backgrounding.md#readme
1047
1040
  [derivation_endpoint plugin]: /doc/plugins/derivation_endpoint.md#readme
1041
+ [derivatives plugin]: /doc/plugins/derivatives.md#readme
1048
1042
  [determine_mime_type plugin]: /doc/plugins/determine_mime_type.md#readme
1049
1043
  [instrumentation plugin]: /doc/plugins/instrumentation.md#readme
1050
1044
  [hanami plugin]: https://github.com/katafrakt/hanami-shrine
1051
1045
  [mongoid plugin]: https://github.com/shrinerb/shrine-mongoid
1052
1046
  [presign_endpoint plugin]: /doc/plugins/presign_endpoint.md#readme
1053
1047
  [pretty_location plugin]: /doc/plugins/pretty_location.md#readme
1054
- [processing plugin]: /doc/plugins/processing.md#readme
1055
1048
  [rack_file plugin]: /doc/plugins/rack_file.md#readme
1049
+ [rom plugin]: https://github.com/shrinerb/shrine-rom
1056
1050
  [sequel plugin]: /doc/plugins/sequel.md#readme
1057
1051
  [signature plugin]: /doc/plugins/signature.md#readme
1058
1052
  [store_dimensions plugin]: /doc/plugins/store_dimensions.md#readme
1059
1053
  [upload_endpoint plugin]: /doc/plugins/upload_endpoint.md#readme
1060
1054
  [validation_helpers plugin]: /doc/plugins/validation_helpers.md#readme
1061
- [versions plugin]: /doc/plugins/versions.md#readme
1055
+ [validation plugin]: /doc/plugins/validation.md#readme
1062
1056
 
1063
1057
  <!-- Demos -->
1064
1058
  [rails demo]: https://github.com/erikdahlstrand/shrine-rails-example