shrine 2.19.3 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +523 -41
  3. data/LICENSE.txt +1 -1
  4. data/README.md +83 -979
  5. data/doc/advantages.md +231 -204
  6. data/doc/attacher.md +304 -153
  7. data/doc/carrierwave.md +297 -226
  8. data/doc/changing_derivatives.md +308 -0
  9. data/doc/changing_location.md +103 -21
  10. data/doc/changing_storage.md +110 -0
  11. data/doc/creating_persistence_plugins.md +132 -0
  12. data/doc/creating_plugins.md +43 -23
  13. data/doc/creating_storages.md +19 -5
  14. data/doc/design.md +147 -97
  15. data/doc/direct_s3.md +38 -28
  16. data/doc/external/articles.md +63 -0
  17. data/doc/external/extensions.md +53 -0
  18. data/doc/external/misc.md +32 -0
  19. data/doc/getting_started.md +1156 -0
  20. data/doc/metadata.md +190 -109
  21. data/doc/multiple_files.md +93 -30
  22. data/doc/paperclip.md +384 -262
  23. data/doc/plugins/activerecord.md +177 -46
  24. data/doc/plugins/add_metadata.md +139 -38
  25. data/doc/plugins/atomic_helpers.md +217 -0
  26. data/doc/plugins/backgrounding.md +156 -98
  27. data/doc/plugins/cached_attachment_data.md +7 -5
  28. data/doc/plugins/column.md +121 -0
  29. data/doc/plugins/data_uri.md +23 -22
  30. data/doc/plugins/default_storage.md +36 -10
  31. data/doc/plugins/default_url.md +30 -13
  32. data/doc/plugins/delete_raw.md +4 -2
  33. data/doc/plugins/derivation_endpoint.md +186 -101
  34. data/doc/plugins/derivatives.md +839 -0
  35. data/doc/plugins/determine_mime_type.md +4 -2
  36. data/doc/plugins/download_endpoint.md +64 -8
  37. data/doc/plugins/dynamic_storage.md +5 -3
  38. data/doc/plugins/entity.md +263 -0
  39. data/doc/plugins/form_assign.md +55 -0
  40. data/doc/plugins/included.md +31 -8
  41. data/doc/plugins/infer_extension.md +21 -10
  42. data/doc/plugins/instrumentation.md +38 -16
  43. data/doc/plugins/keep_files.md +16 -17
  44. data/doc/plugins/metadata_attributes.md +42 -13
  45. data/doc/plugins/mirroring.md +118 -0
  46. data/doc/plugins/model.md +210 -0
  47. data/doc/plugins/module_include.md +4 -2
  48. data/doc/plugins/multi_cache.md +24 -0
  49. data/doc/plugins/persistence.md +101 -0
  50. data/doc/plugins/presign_endpoint.md +9 -4
  51. data/doc/plugins/pretty_location.md +16 -3
  52. data/doc/plugins/processing.md +4 -2
  53. data/doc/plugins/rack_file.md +8 -2
  54. data/doc/plugins/rack_response.md +6 -2
  55. data/doc/plugins/recache.md +4 -2
  56. data/doc/plugins/refresh_metadata.md +49 -9
  57. data/doc/plugins/remote_url.md +84 -47
  58. data/doc/plugins/remove_attachment.md +27 -6
  59. data/doc/plugins/remove_invalid.md +21 -6
  60. data/doc/plugins/restore_cached_data.md +11 -3
  61. data/doc/plugins/sequel.md +159 -35
  62. data/doc/plugins/signature.md +16 -5
  63. data/doc/plugins/store_dimensions.md +14 -2
  64. data/doc/plugins/tempfile.md +4 -2
  65. data/doc/plugins/type_predicates.md +96 -0
  66. data/doc/plugins/upload_endpoint.md +13 -13
  67. data/doc/plugins/upload_options.md +6 -4
  68. data/doc/plugins/{default_url_options.md → url_options.md} +9 -7
  69. data/doc/plugins/validation.md +97 -0
  70. data/doc/plugins/validation_helpers.md +16 -13
  71. data/doc/plugins/versions.md +15 -19
  72. data/doc/processing.md +438 -221
  73. data/doc/refile.md +188 -170
  74. data/doc/release_notes/1.0.0.md +4 -0
  75. data/doc/release_notes/1.1.0.md +6 -2
  76. data/doc/release_notes/1.2.0.md +4 -0
  77. data/doc/release_notes/1.3.0.md +4 -0
  78. data/doc/release_notes/1.4.0.md +4 -0
  79. data/doc/release_notes/1.4.1.md +4 -0
  80. data/doc/release_notes/1.4.2.md +4 -0
  81. data/doc/release_notes/2.0.0.md +4 -0
  82. data/doc/release_notes/2.0.1.md +4 -0
  83. data/doc/release_notes/2.1.0.md +5 -1
  84. data/doc/release_notes/2.1.1.md +4 -0
  85. data/doc/release_notes/2.10.0.md +4 -0
  86. data/doc/release_notes/2.10.1.md +4 -0
  87. data/doc/release_notes/2.11.0.md +4 -0
  88. data/doc/release_notes/2.12.0.md +4 -0
  89. data/doc/release_notes/2.13.0.md +4 -0
  90. data/doc/release_notes/2.14.0.md +5 -1
  91. data/doc/release_notes/2.15.0.md +11 -7
  92. data/doc/release_notes/2.16.0.md +4 -0
  93. data/doc/release_notes/2.17.0.md +4 -0
  94. data/doc/release_notes/2.18.0.md +4 -0
  95. data/doc/release_notes/2.19.0.md +6 -3
  96. data/doc/release_notes/2.2.0.md +4 -0
  97. data/doc/release_notes/2.3.0.md +4 -0
  98. data/doc/release_notes/2.3.1.md +4 -0
  99. data/doc/release_notes/2.4.0.md +4 -0
  100. data/doc/release_notes/2.4.1.md +4 -0
  101. data/doc/release_notes/2.5.0.md +4 -0
  102. data/doc/release_notes/2.6.0.md +4 -0
  103. data/doc/release_notes/2.6.1.md +4 -0
  104. data/doc/release_notes/2.7.0.md +4 -0
  105. data/doc/release_notes/2.8.0.md +4 -0
  106. data/doc/release_notes/2.9.0.md +4 -0
  107. data/doc/release_notes/3.0.0.md +981 -0
  108. data/doc/release_notes/3.0.1.md +22 -0
  109. data/doc/release_notes/3.1.0.md +73 -0
  110. data/doc/release_notes/3.2.0.md +96 -0
  111. data/doc/release_notes/3.2.1.md +31 -0
  112. data/doc/release_notes/3.2.2.md +14 -0
  113. data/doc/release_notes/3.3.0.md +105 -0
  114. data/doc/release_notes/3.4.0.md +35 -0
  115. data/doc/release_notes/3.5.0.md +63 -0
  116. data/doc/release_notes/3.6.0.md +23 -0
  117. data/doc/retrieving_uploads.md +5 -2
  118. data/doc/securing_uploads.md +60 -37
  119. data/doc/storage/file_system.md +20 -3
  120. data/doc/storage/memory.md +19 -0
  121. data/doc/storage/s3.md +122 -78
  122. data/doc/testing.md +141 -133
  123. data/doc/upgrading_to_3.md +708 -0
  124. data/doc/validation.md +54 -90
  125. data/lib/shrine/attacher.rb +292 -169
  126. data/lib/shrine/attachment.rb +13 -46
  127. data/lib/shrine/plugins/_persistence.rb +93 -0
  128. data/lib/shrine/plugins/activerecord.rb +77 -34
  129. data/lib/shrine/plugins/add_metadata.rb +25 -17
  130. data/lib/shrine/plugins/atomic_helpers.rb +119 -0
  131. data/lib/shrine/plugins/backgrounding.rb +77 -113
  132. data/lib/shrine/plugins/cached_attachment_data.rb +6 -15
  133. data/lib/shrine/plugins/column.rb +102 -0
  134. data/lib/shrine/plugins/data_uri.rb +38 -36
  135. data/lib/shrine/plugins/default_storage.rb +45 -15
  136. data/lib/shrine/plugins/default_url.rb +12 -24
  137. data/lib/shrine/plugins/default_url_options.rb +3 -30
  138. data/lib/shrine/plugins/delete_raw.rb +10 -16
  139. data/lib/shrine/plugins/derivation_endpoint.rb +130 -171
  140. data/lib/shrine/plugins/derivatives.rb +645 -0
  141. data/lib/shrine/plugins/determine_mime_type.rb +9 -21
  142. data/lib/shrine/plugins/download_endpoint.rb +118 -133
  143. data/lib/shrine/plugins/dynamic_storage.rb +5 -11
  144. data/lib/shrine/plugins/entity.rb +158 -0
  145. data/lib/shrine/plugins/form_assign.rb +108 -0
  146. data/lib/shrine/plugins/included.rb +6 -6
  147. data/lib/shrine/plugins/infer_extension.rb +17 -20
  148. data/lib/shrine/plugins/instrumentation.rb +59 -43
  149. data/lib/shrine/plugins/keep_files.rb +3 -15
  150. data/lib/shrine/plugins/metadata_attributes.rb +28 -19
  151. data/lib/shrine/plugins/mirroring.rb +142 -0
  152. data/lib/shrine/plugins/model.rb +160 -0
  153. data/lib/shrine/plugins/module_include.rb +3 -3
  154. data/lib/shrine/plugins/multi_cache.rb +27 -0
  155. data/lib/shrine/plugins/presign_endpoint.rb +27 -28
  156. data/lib/shrine/plugins/pretty_location.rb +15 -9
  157. data/lib/shrine/plugins/processing.rb +22 -9
  158. data/lib/shrine/plugins/rack_file.rb +2 -42
  159. data/lib/shrine/plugins/rack_response.rb +21 -10
  160. data/lib/shrine/plugins/recache.rb +6 -5
  161. data/lib/shrine/plugins/refresh_metadata.rb +13 -11
  162. data/lib/shrine/plugins/remote_url.rb +49 -49
  163. data/lib/shrine/plugins/remove_attachment.rb +12 -6
  164. data/lib/shrine/plugins/remove_invalid.rb +19 -8
  165. data/lib/shrine/plugins/restore_cached_data.rb +13 -7
  166. data/lib/shrine/plugins/sequel.rb +86 -36
  167. data/lib/shrine/plugins/signature.rb +10 -16
  168. data/lib/shrine/plugins/store_dimensions.rb +35 -40
  169. data/lib/shrine/plugins/tempfile.rb +1 -3
  170. data/lib/shrine/plugins/type_predicates.rb +113 -0
  171. data/lib/shrine/plugins/upload_endpoint.rb +28 -24
  172. data/lib/shrine/plugins/upload_options.rb +14 -15
  173. data/lib/shrine/plugins/url_options.rb +31 -0
  174. data/lib/shrine/plugins/validation.rb +80 -0
  175. data/lib/shrine/plugins/validation_helpers.rb +35 -58
  176. data/lib/shrine/plugins/versions.rb +107 -87
  177. data/lib/shrine/plugins.rb +22 -0
  178. data/lib/shrine/storage/file_system.rb +46 -64
  179. data/lib/shrine/storage/linter.rb +42 -7
  180. data/lib/shrine/storage/memory.rb +49 -0
  181. data/lib/shrine/storage/s3.rb +173 -160
  182. data/lib/shrine/uploaded_file.rb +32 -32
  183. data/lib/shrine/version.rb +3 -3
  184. data/lib/shrine.rb +87 -150
  185. data/shrine.gemspec +11 -12
  186. metadata +92 -82
  187. data/doc/migrating_storage.md +0 -76
  188. data/doc/plugins/backup.md +0 -31
  189. data/doc/plugins/copy.md +0 -24
  190. data/doc/plugins/delete_promoted.md +0 -12
  191. data/doc/plugins/direct_upload.md +0 -172
  192. data/doc/plugins/hooks.md +0 -58
  193. data/doc/plugins/logging.md +0 -42
  194. data/doc/plugins/migration_helpers.md +0 -60
  195. data/doc/plugins/moving.md +0 -19
  196. data/doc/plugins/multi_delete.md +0 -20
  197. data/doc/plugins/parallelize.md +0 -16
  198. data/doc/plugins/parsed_json.md +0 -23
  199. data/doc/regenerating_versions.md +0 -143
  200. data/lib/shrine/plugins/background_helpers.rb +0 -5
  201. data/lib/shrine/plugins/backup.rb +0 -90
  202. data/lib/shrine/plugins/copy.rb +0 -50
  203. data/lib/shrine/plugins/delete_promoted.rb +0 -20
  204. data/lib/shrine/plugins/direct_upload.rb +0 -217
  205. data/lib/shrine/plugins/hooks.rb +0 -90
  206. data/lib/shrine/plugins/logging.rb +0 -142
  207. data/lib/shrine/plugins/migration_helpers.rb +0 -70
  208. data/lib/shrine/plugins/moving.rb +0 -57
  209. data/lib/shrine/plugins/multi_delete.rb +0 -32
  210. data/lib/shrine/plugins/parallelize.rb +0 -78
  211. data/lib/shrine/plugins/parsed_json.rb +0 -29
@@ -1,34 +1,12 @@
1
- # Derivation Endpoint
1
+ ---
2
+ title: Derivation Endpoint
3
+ ---
2
4
 
3
5
  The [`derivation_endpoint`][derivation_endpoint] plugin provides a Rack app for
4
6
  dynamically processing uploaded files on request. This allows you to create
5
7
  URLs to files that might not have been generated yet, and have the endpoint
6
8
  process them on-the-fly.
7
9
 
8
- ## Contents
9
-
10
- * [Quick start](#quick-start)
11
- * [How it works](#how-it-works)
12
- - [Performance](#performance)
13
- * [Derivation response](#derivation-response)
14
- * [Dynamic settings](#dynamic-settings)
15
- * [Host](#host)
16
- * [Prefix](#prefix)
17
- * [Expiration](#expiration)
18
- * [Response headers](#response-headers)
19
- - [Content Type](#content-type)
20
- - [Content Disposition](#content-disposition)
21
- - [Cache Control](#cache-control)
22
- * [Uploading](#uploading)
23
- - [Redirecting](#redirecting)
24
- - [Deleting derivatives](#deleting-derivatives)
25
- * [Cache busting](#cache-busting)
26
- * [Accessing source file](#accessing-source-file)
27
- * [Downloading](#downloading)
28
- - [Skipping download](#skipping-download)
29
- * [Derivation API](#derivation-api)
30
- * [Plugin Options](#plugin-options)
31
-
32
10
  ## Quick start
33
11
 
34
12
  We first load the plugin, providing a secret key and a path prefix to where the
@@ -57,7 +35,7 @@ apply to an attached file. For example, we can generate image thumbnails using
57
35
  the [ImageProcessing] gem:
58
36
 
59
37
  ```rb
60
- gem "image_processing", "~> 1.2"
38
+ gem "image_processing", "~> 1.8"
61
39
  ```
62
40
  ```rb
63
41
  require "image_processing/mini_magick"
@@ -76,7 +54,7 @@ Now we can generate "derivation" URLs from attached files, which on request
76
54
  will call the derivation block we defined.
77
55
 
78
56
  ```rb
79
- photo.image.derivation_url(:thumbnail, "600", "400")
57
+ photo.image.derivation_url(:thumbnail, 600, 400)
80
58
  #=> "/derivations/image/thumbnail/600/400/eyJpZCI6ImZvbyIsInN0b3JhZ2UiOiJzdG9yZSJ9?signature=..."
81
59
  ```
82
60
 
@@ -102,23 +80,26 @@ derivation URLs, preventing potential DoS attacks.
102
80
 
103
81
  The derivation endpoint then extracts the source file data, derivation name and
104
82
  arguments from the request URL, and calls the corresponding derivation block,
105
- passing the downloaded source file and derivation arguments.
83
+ passing the downloaded source file and derivation arguments. The derivation
84
+ block is evaluated within the context of a
85
+ [`Shrine::Derivation`](#derivation-api) instance.
106
86
 
107
87
  ```rb
108
88
  derivation :thumbnail do |file, arg1, arg2, ...|
89
+ self #=> #<Shrine::Derivation>
90
+
109
91
  file #=> #<Tempfile:...> (source file downloaded to disk)
110
92
  arg1 #=> "600" (first derivation argument in #derivation_url)
111
93
  arg2 #=> "400" (second derivation argument in #derivation_url)
112
94
 
113
95
  # ... do processing ...
114
96
 
115
- # return result as a File/Tempfile object or String/Pathname path
97
+ # return result as a File or Tempfile object
116
98
  end
117
99
  ```
118
100
 
119
- The derivation block is expected to return the processed file is a
120
- `File`/`Tempfile` object or a `String`/`Pathname` path. The resulting file is
121
- then rendered in the HTTP response.
101
+ The derivation block is expected to return the processed file as a `File` or
102
+ `Tempfile` object. The resulting file is then rendered in the HTTP response.
122
103
 
123
104
  ### Performance
124
105
 
@@ -216,7 +197,8 @@ Rails.application.routes.draw do
216
197
  end
217
198
  end
218
199
  end
219
-
200
+ ```
201
+ ```rb
220
202
  # app/controllers/photos_controller.rb
221
203
  class PhotosController < ApplicationController
222
204
  def thumbnail
@@ -349,6 +331,29 @@ uploaded_file.derivation_url(:thumbnail, expires_in: 90)
349
331
  #=> ".../thumbnail/eyJpZCI6ImZvbyIsInN?expires_at=1547843568&signature=..."
350
332
  ```
351
333
 
334
+ ## Custom signer
335
+
336
+ The derivation URLs are signed by default, and the signature is checked when
337
+ the URLs are requested, which prevents tampering. If you have URL expiration
338
+ turned on, this may prevent your CDN from caching the response.
339
+
340
+ In this case, you may need to do custom CDN-specific URL signing. You can
341
+ bypass Shrine's default signing by passing a custom signer:
342
+
343
+ ```rb
344
+ require "aws-sdk-cloudfront"
345
+ signer = Aws::CloudFront::UrlSigner.new(key_pair_id: "...", private_key: "...")
346
+
347
+ plugin :derivation_endpoint,
348
+ expires_in: 90,
349
+ signer: -> (url, expires_in:) do
350
+ signer.signed_url(url, expires: Time.now.to_i + expires_in)
351
+ end
352
+ ```
353
+
354
+ When `:signer` option is used, the `:secret_key` option is not required, as
355
+ that secret is only used for default signing.
356
+
352
357
  ## Response headers
353
358
 
354
359
  ### Content Type
@@ -430,6 +435,8 @@ fetch the original uploaded file, call the derivation block, upload the
430
435
  derivative to the storage, and serve the derivative. If the derivative does
431
436
  exist on checking, the endpoint will download the derivative and serve it.
432
437
 
438
+ ### Upload location
439
+
433
440
  The default upload location for derivatives is `<source id>/<name>-<args>`.
434
441
  This can be changed with the `:upload_location` option:
435
442
 
@@ -445,6 +452,8 @@ response won't know the appropriate `Content-Type` header value to set, and the
445
452
  generic `application/octet-stream` will be used. It's recommended to use the
446
453
  [`:type`](#content-type) option to set the appropriate `Content-Type` value.
447
454
 
455
+ ### Upload storage
456
+
448
457
  The target storage used is the same as for the source uploaded file. The
449
458
  `:upload_storage` option can be used to specify a different Shrine storage:
450
459
 
@@ -453,6 +462,8 @@ plugin :derivation_endpoint, upload: true,
453
462
  upload_storage: :thumbnail_storage
454
463
  ```
455
464
 
465
+ ### Upload options
466
+
456
467
  Additional storage-specific upload options can be passed via `:upload_options`:
457
468
 
458
469
  ```rb
@@ -460,6 +471,8 @@ plugin :derivation_endpoint, upload: true,
460
471
  upload_options: { acl: "public-read" }
461
472
  ```
462
473
 
474
+ ### Upload open options
475
+
463
476
  Additional storage-specific download options for the uploaded derivation result
464
477
  can be passed via `:upload_open_options`:
465
478
 
@@ -480,8 +493,7 @@ plugin :derivation_endpoint, upload: true,
480
493
  upload_redirect: true
481
494
  ```
482
495
 
483
- In that case additional storage-specific URL options can be passed in for the
484
- redirect URL:
496
+ Additional storage-specific URL options can be passed in for the redirect URL:
485
497
 
486
498
  ```rb
487
499
  plugin :derivation_endpoint, upload: true,
@@ -489,20 +501,54 @@ plugin :derivation_endpoint, upload: true,
489
501
  upload_redirect_url_options: { public: true }
490
502
  ```
491
503
 
492
- If you are using the local filesystem storage, then redirecting does not make
493
- sense.
504
+ Note that redirecting only makes sense if you're using remote storage services
505
+ such as AWS S3 or Google Cloud Storage.
494
506
 
495
507
  ### Deleting derivatives
496
508
 
497
- When you use the `:upload` options and upload the derivatives to storage, there
498
- will come a time when you need to delete the derivatives because the original
499
- file is being replaced, deleted, or some other reason. In this case, you can
500
- delete the derivatives before deleting the record or updating the record with
501
- the new original file.
509
+ When the original attachment is deleted, its uploaded derivatives will not be
510
+ automatically deleted, you will need to do the deletion manually. If you're
511
+ using [backgrounding], you can do this in your `DestroyJob`.
512
+
513
+ If your storage implements `#delete_prefixed`, and you're using the default
514
+ [`:upload_location`](#upload-location), you can delete the directory containing
515
+ derivatives:
516
+
517
+ ```rb
518
+ class DestroyJob < ActiveJob::Base
519
+ def perform(attacher_class, data)
520
+ # ... destroy attached file ...
521
+
522
+ derivatives_directory = attacher.file.id + "/"
523
+ storage = attacher.store.storage
524
+
525
+ storage.delete_prefixed(derivatives_directory)
526
+ end
527
+ end
528
+ ```
529
+
530
+ Alternatively, you can delete each derivative individually:
502
531
 
503
532
  ```rb
504
- # photo is the model and image is the file attachment
505
- photo.image.derivation(:thumbnail).delete
533
+ class ImageUploader < Shrine
534
+ DERIVATIONS = [
535
+ [:thumbnail, 800, 800],
536
+ [:thumbnail, 600, 400],
537
+ [:thumbnail, 400, 300],
538
+ ...
539
+ ]
540
+ end
541
+ ```
542
+ ```rb
543
+ class DestroyJob < ActiveJob::Base
544
+ def perform(attacher_class, data)
545
+ # ... destroy attached file ...
546
+
547
+ attacher.shrine_class::DERIVATIONS.each do |args|
548
+ attacher.file.derivation(*args).delete
549
+ end
550
+ end
551
+ end
506
552
  ```
507
553
 
508
554
  ## Cache busting
@@ -538,50 +584,38 @@ uploaded_file.derivation_url(:thumbnail, version: 1)
538
584
 
539
585
  ## Accessing source file
540
586
 
541
- If you want to access the source `UploadedFile` object when deriving, you can
542
- set `:include_uploaded_file` to `true`.
543
-
544
- ```rb
545
- plugin :derivation_endpoint, include_uploaded_file: true
546
- ```
547
-
548
- Now the source `UploadedFile` will be passed as the second argument of the
549
- derivation block:
587
+ Inside the derivation block we can access the source `UploadedFile` object via
588
+ `Shrine::Derivation#source`:
550
589
 
551
590
  ```rb
552
- derivation :thumbnail do |file, uploaded_file, width, height|
553
- uploaded_file #=> #<Shrine::UploadedFile>
554
- uploaded_file.id #=> "9a7d1bfdad24a76f9cfaff137fe1b5c7.jpg"
555
- uploaded_file.storage_key #=> "store"
556
- uploaded_file.metadata #=> {}
591
+ derivation :thumbnail do |file, width, height|
592
+ source #=> #<Shrine::UploadedFile>
593
+ source.id #=> "9a7d1bfdad24a76f9cfaff137fe1b5c7.jpg"
594
+ source.storage_key #=> :store
595
+ source.metadata #=> {}
557
596
 
558
597
  # ...
559
598
  end
560
599
  ```
561
600
 
562
- By default original metadata that were extracted on attachment won't be
563
- available in the derivation block. This is because metadata we want to have
564
- available would need to be serialized into the derivation URL, which would make
565
- it longer. However, you can opt in for the metadata you need with the
566
- `:metadata` option:
601
+ By default, when using the derivation endpoint, original metadata of the source
602
+ file won't be available in the derivation block. This is because any metadata
603
+ we would want to have available would need to be serialized into the derivation
604
+ URL, which would make it longer. Instead, you can opt in for the metadata you
605
+ want to have available:
567
606
 
568
607
  ```rb
569
608
  plugin :derivation_endpoint, metadata: ["filename", "mime_type"]
570
- ```
571
-
572
- Now `filename` and `mime_type` metadata values will be available in the
573
- derivation block:
574
609
 
575
- ```rb
576
- derivation :thumbnail do |file, uploaded_file, width, height|
577
- uploaded_file.metadata #=>
610
+ derivation :thumbnail do |file, width, height|
611
+ source.metadata #=>
578
612
  # {
579
613
  # "filename" => "nature.jpg",
580
614
  # "mime_type" => "image/jpeg"
581
615
  # }
582
616
 
583
- uploaded_file.original_filename #=> "nature.jpg"
584
- uploaded_file.mime_type #=> "image/jpeg"
617
+ source.original_filename #=> "nature.jpg"
618
+ source.mime_type #=> "image/jpeg"
585
619
 
586
620
  # ...
587
621
  end
@@ -602,17 +636,9 @@ plugin :derivation_endpoint, download_options: {
602
636
  }
603
637
  ```
604
638
 
605
- If the source file has been deleted, the error the storage raises when
606
- attempting to download it will be propagated by default. For
607
- `Shrine.derivation_endpoint` and `Shrine.derivation_response` you can have
608
- these errors converted to 404 responses by adding them to `:download_errors`:
609
-
610
- ```rb
611
- plugin :derivation_endpoint, download_errors: [
612
- Errno::ENOENT, # raised by Shrine::Storage::FileSystem
613
- Aws::S3::Errors::NotFound, # raised by Shrine::Storage::S3
614
- ]
615
- ```
639
+ If the source file was not found, `Shrine::Derivation::SourceNotFound`
640
+ exception is raised. In a derivation response this is converted into a `404 Not
641
+ Found` response.
616
642
 
617
643
  ### Skipping download
618
644
 
@@ -621,15 +647,8 @@ disk for you, you can set `:download` to `false`.
621
647
 
622
648
  ```rb
623
649
  plugin :derivation_endpoint, download: false
624
- ```
625
-
626
- In this case the `UploadedFile` object is yielded to the derivation block
627
- instead of the raw file:
628
-
629
- ```rb
630
- derivation :thumbnail do |uploaded_file, width, height|
631
- uploaded_file #=> #<Shrine::UploadedFile>
632
650
 
651
+ derivation :thumbnail do |width, height| # source file is not downloaded
633
652
  # ...
634
653
  end
635
654
  ```
@@ -639,10 +658,10 @@ One use case for this is delegating processing to a 3rd-party service:
639
658
  ```rb
640
659
  require "down/http"
641
660
 
642
- derivation :thumbnail do |uploaded_file, width, height|
661
+ derivation :thumbnail do |width, height|
643
662
  # generate the thumbnail using ImageOptim.com
644
663
  down = Down::Http.new(method: :post)
645
- down.download("https://im2.io/<USERNAME>/#{width}x#{height}/#{uploaded_file.url}")
664
+ down.download("https://im2.io/<USERNAME>/#{width}x#{height}/#{source.url}")
646
665
  end
647
666
  ```
648
667
 
@@ -735,13 +754,20 @@ uploaded_file #=> #<Shrine::UploadedFile>
735
754
  uploaded_file.id #=> "bcfd0d67e4a8ec2dc9a6d7ddcf3825a1/thumbnail-500-500"
736
755
  ```
737
756
 
738
- If not given any arguments, it generates the derivative before uploading it.
757
+ It can also be called without arguments, in which case it will generate a new
758
+ derivative and upload it.
759
+
760
+ ```rb
761
+ derivation.upload # generates derivative and uploads it
762
+ ```
763
+
764
+ Any additional options will be passed to the uploader.
739
765
 
740
766
  ### `#retrieve`
741
767
 
742
- `Derivation#retrieve` method returns the uploaded derivative file. If the file
743
- exists on the storage, it returns an `UploadedFile` object, otherwise `nil` is
744
- returned.
768
+ `Derivation#retrieve` method returns `Shrine::UploadedFile` object pointing to
769
+ the uploaded derivative if it exists. If the uploaded derivative does not
770
+ exist, `nil` is returned.
745
771
 
746
772
  ```rb
747
773
  uploaded_file = derivation.retrieve
@@ -749,6 +775,18 @@ uploaded_file #=> #<Shrine::UploadedFile>
749
775
  uploaded_file.id #=> "bcfd0d67e4a8ec2dc9a6d7ddcf3825a1/thumbnail-500-500"
750
776
  ```
751
777
 
778
+ ### `#opened`
779
+
780
+ `Derivation#opened` method returns opened `Shrine::UploadedFile` object pointing
781
+ to the uploaded derivative if it exists. If the uploaded derivative does not
782
+ exist, `nil` is returned.
783
+
784
+ ```rb
785
+ uploaded_file = derivation.opened
786
+ uploaded_file #=> #<Shrine::UploadedFile>
787
+ uploaded_file.id #=> "bcfd0d67e4a8ec2dc9a6d7ddcf3825a1/thumbnail-500-500"
788
+ ```
789
+
752
790
  ### `#delete`
753
791
 
754
792
  `Derivation#delete` method deletes the uploaded derivative file from the
@@ -774,15 +812,14 @@ derivation.option(:upload_location)
774
812
  | `:cache_control` | Hash of directives for the `Cache-Control` response header | `{ public: true, max_age: 365*24*60*60 }` |
775
813
  | `:disposition` | Whether the browser should attempt to render the derivative (`inline`) or prompt the user to download the file to disk (`attachment`) | `inline` |
776
814
  | `:download` | Whether the source uploaded file should be downloaded to disk when the derivation block is called | `true` |
777
- | `:download_errors` | List of error classes that will be converted to a `404 Not Found` response by the derivation endpoint | `[]` |
778
815
  | `:download_options` | Additional options to pass when downloading the source uploaded file | `{}` |
779
816
  | `:expires_in` | Number of seconds after which the URL will not be available anymore | `nil` |
780
817
  | `:filename` | Filename the browser will assume when the derivative is downloaded to disk | `<name>-<args>-<source id basename>` |
781
- | `:host` | URL host to use when generated URLs | `nil` |
782
- | `:include_uploaded_file` | Whether to include the source uploaded file in the derivation block arguments | `false` |
818
+ | `:host` | URL host to use when for URLs | `nil` |
783
819
  | `:metadata` | List of metadata keys the source uploaded file should include in the derivation block | `[]` |
784
820
  | `:prefix` | Path prefix added to the URLs | `nil` |
785
821
  | `:secret_key` | Key used to sign derivation URLs in order to prevent tampering | required |
822
+ | `:signer` | Proc accepting URL and query params used for custom signing of URLs. | `nil` |
786
823
  | `:type` | Media type returned in the `Content-Type` response header in the derivation response | determined from derivative's extension when possible |
787
824
  | `:upload` | Whether the generated derivatives will be cached on the storage | `false` |
788
825
  | `:upload_location` | Location to which the derivatives will be uploaded on the storage | `<source id>/<name>-<args>` |
@@ -793,8 +830,56 @@ derivation.option(:upload_location)
793
830
  | `:upload_storage` | Storage to which the derivations will be uploaded | same storage as the source file |
794
831
  | `:version` | Version number to append to the URL for cache busting | `nil` |
795
832
 
796
- [derivation_endpoint]: /lib/shrine/plugins/derivation_endpoint.rb
833
+ ## Instrumentation
834
+
835
+ If the `instrumentation` plugin has been loaded, the `determine_mime_type` plugin
836
+ adds instrumentation around derivation processing.
837
+
838
+ ```rb
839
+ # instrumentation plugin needs to be loaded *before* derivation_endpoint
840
+ plugin :instrumentation
841
+ plugin :derivation_endpoint
842
+ ```
843
+
844
+ Derivation processing will trigger a `derivation.shrine` event with the
845
+ following payload:
846
+
847
+ | Key | Description |
848
+ | :-- | :---- |
849
+ | `:derivation` | `Shrine::Derivation` object for this processing |
850
+ | `:uploader` | The uploader class that sent the event |
851
+
852
+ A default log subscriber is added as well which logs these events:
853
+
854
+ ```
855
+ Derivation (492ms) – {:name=>:thumbnail, :args=>[600, 600], :uploader=>Shrine}
856
+ ```
857
+
858
+ You can also use your own log subscriber:
859
+
860
+ ```rb
861
+ plugin :derivation_endpoint, log_subscriber: -> (event) {
862
+ Shrine.logger.info JSON.generate(
863
+ name: event.name,
864
+ duration: event.duration,
865
+ name: event[:derivation].name,
866
+ args: event[:derivation].args,
867
+ )
868
+ }
869
+ ```
870
+ ```
871
+ {"name":"derivation","duration":492,"name":"thumbnail","args":[600,600],"uploader":"Shrine"}
872
+ ```
873
+
874
+ Or disable logging altogether:
875
+
876
+ ```rb
877
+ plugin :derivation_endpoint, log_subscriber: nil
878
+ ```
879
+
880
+ [derivation_endpoint]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/derivation_endpoint.rb
797
881
  [ImageProcessing]: https://github.com/janko/image_processing
798
882
  [`Content-Type`]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type
799
883
  [`Content-Disposition`]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
800
884
  [`Cache-Control`]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
885
+ [backgrounding]: https://shrinerb.com/docs/plugins/backgrounding