shrine 3.0.1 → 3.3.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 (103) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +82 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +15 -5
  5. data/doc/advantages.md +33 -16
  6. data/doc/attacher.md +2 -2
  7. data/doc/carrierwave.md +78 -34
  8. data/doc/changing_derivatives.md +39 -39
  9. data/doc/design.md +134 -85
  10. data/doc/direct_s3.md +1 -0
  11. data/doc/external/articles.md +57 -45
  12. data/doc/external/extensions.md +41 -35
  13. data/doc/external/misc.md +23 -8
  14. data/doc/getting_started.md +177 -112
  15. data/doc/metadata.md +79 -43
  16. data/doc/multiple_files.md +6 -4
  17. data/doc/paperclip.md +119 -42
  18. data/doc/plugins/activerecord.md +1 -1
  19. data/doc/plugins/add_metadata.md +112 -35
  20. data/doc/plugins/atomic_helpers.md +41 -3
  21. data/doc/plugins/backgrounding.md +12 -2
  22. data/doc/plugins/column.md +36 -7
  23. data/doc/plugins/data_uri.md +2 -2
  24. data/doc/plugins/default_url.md +6 -3
  25. data/doc/plugins/derivation_endpoint.md +26 -28
  26. data/doc/plugins/derivatives.md +238 -171
  27. data/doc/plugins/determine_mime_type.md +2 -2
  28. data/doc/plugins/download_endpoint.md +5 -5
  29. data/doc/plugins/dynamic_storage.md +1 -1
  30. data/doc/plugins/form_assign.md +5 -5
  31. data/doc/plugins/included.md +25 -5
  32. data/doc/plugins/infer_extension.md +11 -2
  33. data/doc/plugins/instrumentation.md +1 -1
  34. data/doc/plugins/metadata_attributes.md +22 -10
  35. data/doc/plugins/mirroring.md +1 -1
  36. data/doc/plugins/persistence.md +11 -1
  37. data/doc/plugins/refresh_metadata.md +5 -4
  38. data/doc/plugins/remote_url.md +8 -3
  39. data/doc/plugins/remove_invalid.md +9 -1
  40. data/doc/plugins/signature.md +11 -2
  41. data/doc/plugins/store_dimensions.md +12 -2
  42. data/doc/plugins/type_predicates.md +96 -0
  43. data/doc/plugins/upload_endpoint.md +7 -11
  44. data/doc/plugins/upload_options.md +1 -1
  45. data/doc/plugins/url_options.md +4 -4
  46. data/doc/plugins/validation.md +14 -4
  47. data/doc/plugins/validation_helpers.md +3 -3
  48. data/doc/plugins/versions.md +7 -7
  49. data/doc/processing.md +290 -127
  50. data/doc/refile.md +39 -18
  51. data/doc/release_notes/2.19.0.md +1 -1
  52. data/doc/release_notes/2.8.0.md +1 -1
  53. data/doc/release_notes/3.0.0.md +1 -1
  54. data/doc/release_notes/3.0.1.md +4 -0
  55. data/doc/release_notes/3.1.0.md +73 -0
  56. data/doc/release_notes/3.2.0.md +96 -0
  57. data/doc/release_notes/3.2.1.md +31 -0
  58. data/doc/release_notes/3.2.2.md +14 -0
  59. data/doc/release_notes/3.3.0.md +105 -0
  60. data/doc/securing_uploads.md +3 -3
  61. data/doc/storage/file_system.md +1 -1
  62. data/doc/storage/memory.md +19 -0
  63. data/doc/storage/s3.md +105 -82
  64. data/doc/testing.md +2 -2
  65. data/doc/upgrading_to_3.md +97 -49
  66. data/doc/validation.md +3 -2
  67. data/lib/shrine.rb +8 -8
  68. data/lib/shrine/attacher.rb +24 -14
  69. data/lib/shrine/attachment.rb +5 -5
  70. data/lib/shrine/plugins.rb +22 -0
  71. data/lib/shrine/plugins/activerecord.rb +1 -1
  72. data/lib/shrine/plugins/add_metadata.rb +18 -7
  73. data/lib/shrine/plugins/backgrounding.rb +2 -2
  74. data/lib/shrine/plugins/default_storage.rb +6 -6
  75. data/lib/shrine/plugins/default_url.rb +1 -1
  76. data/lib/shrine/plugins/derivation_endpoint.rb +12 -7
  77. data/lib/shrine/plugins/derivatives.rb +61 -29
  78. data/lib/shrine/plugins/determine_mime_type.rb +3 -3
  79. data/lib/shrine/plugins/entity.rb +6 -6
  80. data/lib/shrine/plugins/mirroring.rb +8 -8
  81. data/lib/shrine/plugins/model.rb +3 -3
  82. data/lib/shrine/plugins/presign_endpoint.rb +16 -4
  83. data/lib/shrine/plugins/pretty_location.rb +1 -1
  84. data/lib/shrine/plugins/processing.rb +1 -1
  85. data/lib/shrine/plugins/refresh_metadata.rb +2 -2
  86. data/lib/shrine/plugins/remote_url.rb +3 -3
  87. data/lib/shrine/plugins/remove_attachment.rb +5 -0
  88. data/lib/shrine/plugins/remove_invalid.rb +10 -5
  89. data/lib/shrine/plugins/sequel.rb +1 -1
  90. data/lib/shrine/plugins/signature.rb +7 -6
  91. data/lib/shrine/plugins/store_dimensions.rb +22 -11
  92. data/lib/shrine/plugins/type_predicates.rb +113 -0
  93. data/lib/shrine/plugins/upload_endpoint.rb +10 -5
  94. data/lib/shrine/plugins/upload_options.rb +2 -2
  95. data/lib/shrine/plugins/url_options.rb +2 -2
  96. data/lib/shrine/plugins/validation.rb +9 -7
  97. data/lib/shrine/storage/linter.rb +4 -4
  98. data/lib/shrine/storage/memory.rb +5 -3
  99. data/lib/shrine/storage/s3.rb +117 -38
  100. data/lib/shrine/uploaded_file.rb +0 -1
  101. data/lib/shrine/version.rb +2 -2
  102. data/shrine.gemspec +7 -8
  103. metadata +25 -31
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0b327565465d4140206d1f88433647e7959b6c56ecbdea7d433f1aa5eb01825d
4
- data.tar.gz: c19fb7f15299b1d061325f8f83e790f44481456fbc9730d4a909923193dde1a3
3
+ metadata.gz: 8cfa59ed1f6143ee9298ede17eeda07dba85f0f9c3309a5b7a9e7f6c41399f29
4
+ data.tar.gz: 67a64a3a4f40c34797ca04279af73829acf4071eb118f78addefdbaa15e048da
5
5
  SHA512:
6
- metadata.gz: 897bbe8787b3a1f7e59db3e6beebbc91b32ec5e4c19cd832029e05205425c12d837bf8475f21949c23a6c805504da45a0937de0d3dc9f50d3d35921b5f6a7901
7
- data.tar.gz: 995b0ada0e5bdb2c4e198304d913f6cfe22d8814328d58bf559490ea572ac3d5555f3eb15fce898ae423ff54f76ba3bcbbeb7f6e05470ddca8acee37ee675455
6
+ metadata.gz: e87a3dbb80a304f8af559b9c3d4e8badf8e47e4377afd74fe08d570042d65358d44878c4a0366fa3cded98fe166083275e86c61f3b51d28d35e070e0233dea35
7
+ data.tar.gz: 83c93e76bf5513ab317ccabbdda86ce90f760e7b898dc9f40036af3e7ec915f48e55bd6f8efcf8661dacea672ce6b24b450db217815b062881169c8c90fd0cd3
@@ -1,3 +1,85 @@
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
+
37
+ ## 3.2.2 (2020-08-05)
38
+
39
+ * `s3` – Fix `S3#open` not working on aws-sdk-core 3.104 and above (@janko)
40
+
41
+ ## 3.2.1 (2020-01-12)
42
+
43
+ * `derivation_endpoint` – Use `Rack::Files` constant on Rack >= 2.1 (@janko)
44
+
45
+ * Fix Ruby 2.7 warnings regarding separation of positional and keyword arguments (@janko)
46
+
47
+ * `s3` – Make `S3#open` handle empty S3 objects (@janko)
48
+
49
+ ## 3.2.0 (2019-12-17) [[release notes]](https://shrinerb.com/docs/release_notes/3.2.0)
50
+
51
+ * `validation` – Run validation on `Attacher#attach` & `Attacher#attach_cached` instead of `Attacher#change` (@janko)
52
+
53
+ * `remove_invalid` – Activate also when `Attacher#validate` is run manually (@janko)
54
+
55
+ * `remove_invalid` – Fix incompatibility with `derivatives` plugin (@janko)
56
+
57
+ * `type_predicates` – Add new plugin with convenient `UploadedFile` predicate methods based on MIME type (@janko)
58
+
59
+ * `core` – Allow assigning back current attached file data (@janko)
60
+
61
+ * `derivatives` – Fix `:derivative` value inconsistency when derivatives are being promoted (@janko)
62
+
63
+ * `add_metadata` – Add `#add_metadata` method for adding metadata to uploaded files (@janko)
64
+
65
+ * `derivatives` – Add `:io` and `:attacher` values to instrumentation event payload (@janko)
66
+
67
+ ## 3.1.0 (2019-11-15) [[release notes]](https://shrinerb.com/docs/release_notes/3.1.0)
68
+
69
+ * `default_storage` – Coerce storage key to symbol in `Attacher#cache_key` & `Attacher#store_key` (@janko)
70
+
71
+ * `core` – Coerce storage key to symbol in `Attacher#cache_key` & `Attacher#store_key` (@janko)
72
+
73
+ * `add_metadata` – Define metadata methods only for the target uploader class (@janko)
74
+
75
+ * `derivatives` – Add `:storage` option to `Attacher#create_derivatives` (@janko)
76
+
77
+ * `store_dimensions` – Propagate exceptions on loading `ruby-vips` in `:vips` analyzer (@janko)
78
+
79
+ * `signature` – Allow skipping rewinding by passing `rewind: false` to `Shrine.signature` (@janko)
80
+
81
+ * `derivatives` – Add `Attacher.derivatives` alias for `Attacher.derivatives_processor` (@janko)
82
+
1
83
  ## 3.0.1 (2019-10-17) [[release notes]](https://shrinerb.com/docs/release_notes/3.0.1)
2
84
 
3
85
  * `metadata_attributes` – Fix exception being raised when there is no attached file (@janko)
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2015-2017 Janko Marohnić
3
+ Copyright (c) 2015-2019 Janko Marohnić
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,18 +1,22 @@
1
1
  # [Shrine]
2
2
 
3
+ <img src="https://shrinerb.com/img/logo.png" width="100" alt="Shrine logo: a red paperclip" align="right" />
4
+
3
5
  Shrine is a toolkit for handling file attachments in Ruby applications. Some highlights:
4
6
 
5
7
  * **Modular design** – the [plugin system] allows you to load only the functionality you need
6
8
  * **Memory friendly** – streaming uploads and [downloads][Retrieving Uploads] make it work great with large files
7
9
  * **Cloud storage** – store files on [disk][FileSystem], [AWS S3][S3], [Google Cloud][GCS], [Cloudinary] and others
8
10
  * **Persistence integrations** – works with [Sequel], [ActiveRecord], [ROM], [Hanami] and [Mongoid] and others
9
- * **Flexible processing** – generate thumbnails [up front] or [on-the-fly] using [ImageMagick] or [libvips]
11
+ * **Flexible processing** – generate thumbnails [eagerly] or [on-the-fly] using [ImageMagick] or [libvips]
10
12
  * **Metadata validation** – [validate files][validation] based on [extracted metadata][metadata]
11
13
  * **Direct uploads** – upload asynchronously [to your app][simple upload] or [to the cloud][presigned upload] using [Uppy]
12
14
  * **Resumable uploads** – make large file uploads [resumable][resumable upload] on [S3][uppy-s3_multipart] or [tus][tus-ruby-server]
13
15
  * **Background jobs** – built-in support for [background processing][backgrounding] that supports [any backgrounding library][Backgrounding Libraries]
14
16
 
15
- Please follow along with the **[Getting Started guide]**.
17
+ If you're curious how it compares to other file attachment libraries, see the
18
+ [Advantages of Shrine]. Otherwise, follow along with the **[Getting Started
19
+ guide]**.
16
20
 
17
21
  ## Links
18
22
 
@@ -52,7 +56,7 @@ Shrine.plugin :restore_cached_data # extracts metadata for assigned cached fi
52
56
  Next, add the `<name>_data` column to the table you want to attach files to. For
53
57
  an "image" attachment on a `photos` table this would be an `image_data` column:
54
58
 
55
- ```sh
59
+ ```
56
60
  $ rails generate migration add_image_data_to_photos image_data:text
57
61
  ```
58
62
 
@@ -123,6 +127,10 @@ system.
123
127
  * Refile
124
128
  * Active Storage
125
129
 
130
+ ## Contributing
131
+
132
+ Please refer to the [contributing page][Contributing].
133
+
126
134
  ## Code of Conduct
127
135
 
128
136
  Everyone interacting in the Shrine project’s codebases, issue trackers, and
@@ -133,6 +141,7 @@ mailing lists is expected to follow the [Shrine code of conduct][CoC].
133
141
  The gem is available as open source under the terms of the [MIT License].
134
142
 
135
143
  [Shrine]: https://shrinerb.com
144
+ [Advantages of Shrine]: https://shrinerb.com/docs/advantages
136
145
  [plugin system]: https://shrinerb.com/docs/getting-started#plugin-system
137
146
  [Retrieving Uploads]: https://shrinerb.com/docs/retrieving-uploads
138
147
  [FileSystem]: https://shrinerb.com/docs/storage/file-system
@@ -144,8 +153,8 @@ The gem is available as open source under the terms of the [MIT License].
144
153
  [ROM]: https://github.com/shrinerb/shrine-rom
145
154
  [Hanami]: https://github.com/katafrakt/hanami-shrine
146
155
  [Mongoid]: https://github.com/shrinerb/shrine-mongoid
147
- [up front]: https://shrinerb.com/docs/getting-started#processing-up-front
148
- [on-the-fly]: https://shrinerb.com/docs/getting-started#processing-on-the-fly
156
+ [eagerly]: https://shrinerb.com/docs/getting-started#eager-processing
157
+ [on-the-fly]: https://shrinerb.com/docs/getting-started#on-the-fly-processing
149
158
  [ImageMagick]: https://github.com/janko/image_processing/blob/master/doc/minimagick.md#readme
150
159
  [libvips]: https://github.com/janko/image_processing/blob/master/doc/vips.md#readme
151
160
  [validation]: https://shrinerb.com/docs/validation
@@ -165,3 +174,4 @@ The gem is available as open source under the terms of the [MIT License].
165
174
  [Roda]: https://github.com/jeremyevans/roda
166
175
  [CoC]: /CODE_OF_CONDUCT.md
167
176
  [MIT License]: /LICENSE.txt
177
+ [Contributing]: https://github.com/shrinerb/shrine/blob/master/CONTRIBUTING.md
@@ -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
- uplaoded_file.metadata #=> { ... extracted metadata ... }
96
+ uploaded_file.metadata #=> { ... extracted metadata ... }
97
97
 
98
98
  data = uploaded_file.to_json # serialization
99
99
  # ...
@@ -157,21 +157,21 @@ end
157
157
 
158
158
  ## Processing
159
159
 
160
- Most file attachment libraries provide either processing files up front
161
- (Paperclip, CarrierWave) or on-the-fly (Dragonfly, Refile, Active Storage).
160
+ Most file attachment libraries allow you to process files either "eagerly"
161
+ (Paperclip, CarrierWave) or "on-the-fly" (Dragonfly, Refile, Active Storage).
162
162
  However, each approach is suitable for different requirements. For instance,
163
163
  while on-the-fly processing is suitable for fast processing (image thumbnails,
164
164
  document previews), longer running processing (video transcoding, raw images)
165
165
  should be moved into a background job.
166
166
 
167
- That's why Shrine supports both [up front][derivatives] and
167
+ That's why Shrine supports both [eager][derivatives] and
168
168
  [on-the-fly][derivation_endpoint] processing. For example, if you're handling
169
169
  image uploads, you can choose to either generate a set of pre-defined
170
170
  thumbnails during attachment:
171
171
 
172
172
  ```rb
173
173
  class ImageUploader < Shrine
174
- Attacher.derivatives_processor do |original|
174
+ Attacher.derivatives do |original|
175
175
  magick = ImageProcessing::MiniMagick.source(original)
176
176
 
177
177
  {
@@ -261,7 +261,7 @@ gem "streamio-ffmpeg"
261
261
  ```
262
262
  ```rb
263
263
  class VideoUploader < Shrine
264
- Attacher.derivatives_processor do |original|
264
+ Attacher.derivatives do |original|
265
265
  transcoded = Tempfile.new ["transcoded", ".mp4"]
266
266
  screenshot = Tempfile.new ["screenshot", ".jpg"]
267
267
 
@@ -281,7 +281,7 @@ movie.video(:transcoded) #=> #<Shrine::UploadedFile id="7481d6.mp4" ...>
281
281
  movie.video(:screenshot) #=> #<Shrine::UploadedFile id="8f3136.jpg" ...>
282
282
  ```
283
283
 
284
- ## Metadata & Validation
284
+ ## Metadata
285
285
 
286
286
  Shrine automatically [extracts metadata][metadata] from each uploaded file,
287
287
  including derivatives like image thumbnails, and saves them into the database
@@ -289,6 +289,17 @@ column. In addition to filename, filesize, and MIME type that are extracted by
289
289
  default, you can also extract [image dimensions][store_dimensions], or your own
290
290
  [custom metadata][add_metadata].
291
291
 
292
+ ```rb
293
+ class ImageUploader < Shrine
294
+ plugin :determine_mime_type # mime_type
295
+ plugin :store_dimensions # width & height
296
+
297
+ add_metadata :resolution do |io|
298
+ image = MiniMagick::Image.new(io.path)
299
+ image.resolution
300
+ end
301
+ end
302
+ ```
292
303
  ```rb
293
304
  photo.image.metadata #=>
294
305
  # {
@@ -297,23 +308,30 @@ photo.image.metadata #=>
297
308
  # "mime_type" => "image/jpeg",
298
309
  # "width" => 600,
299
310
  # "height" => 400,
311
+ # "resolution" => [72, 72],
300
312
  # ...
301
313
  # }
302
314
  ```
303
315
 
304
- For common metadata you can use the built-in [validators][validation_helpers],
305
- but you can also [validate any custom metadata][custom validations].
316
+ ## Validation
317
+
318
+ For file validations there are [built-in validators][validation_helpers], but
319
+ you can also just use plain Ruby code:
306
320
 
307
321
  ```rb
308
- class DocumentUploader < Shrine
322
+ class ImageUploader < Shrine
323
+ plugin :validation_helpers
324
+
309
325
  Attacher.validate do
310
- # validation macros
311
326
  validate_max_size 10*1024*1024
312
- validate_mime_type %W[application/pdf]
327
+ validate_extension %w[jpg jpeg png webp]
328
+
329
+ if validate_mime_type %W[image/jpeg image/png image/webp]
330
+ validate_max_dimensions [5000, 5000]
313
331
 
314
- # custom validations
315
- if file["page_count"] > 30
316
- errors << "must not have more than 30 pages"
332
+ unless ImageProcessing::MiniMagick.valid_image?(file.download.path)
333
+ error << "seems to be corrupted"
334
+ end
317
335
  end
318
336
  end
319
337
  end
@@ -432,7 +450,6 @@ on top of Rack, so that they can be used with any Ruby web framework.
432
450
  [backgrounding libraries]: https://github.com/shrinerb/shrine/wiki/Backgrounding-Libraries
433
451
  [Down streaming]: https://github.com/janko/down#streaming
434
452
  [validation_helpers]: https://shrinerb.com/docs/plugins/validation_helpers
435
- [custom validations]: https://shrinerb.com/docs/validation#custom-validations
436
453
  [derivatives]: https://shrinerb.com/docs/plugins/derivatives
437
454
  [derivation_endpoint]: https://shrinerb.com/docs/plugins/derivation_endpoint
438
455
  [libvips performance]: https://github.com/libvips/libvips/wiki/Speed-and-memory-use#results
@@ -130,8 +130,8 @@ attacher.attach_cached(file)
130
130
 
131
131
  # sets cached file
132
132
  attacher.attach_cached('{"id":"asdf.jpg","storage":"cache","metadata":{...}}')
133
- attacher.attach_cached("id" => "asdf.jpg", "storage" => "cache", "metadata" => { ... })
134
- attacher.attach_cached(id: "asdf.jpg", storage: "cache", metadata: { ... })
133
+ attacher.attach_cached({ "id" => "asdf.jpg", "storage" => "cache", "metadata" => { ... } })
134
+ attacher.attach_cached({ id: "asdf.jpg", storage: "cache", metadata: { ... } })
135
135
 
136
136
  # unsets attached file
137
137
  attacher.attach_cached(nil)
@@ -1,12 +1,12 @@
1
1
  ---
2
- title: Shrine for CarrierWave Users
2
+ title: Upgrading from CarrierWave
3
3
  ---
4
4
 
5
5
  This guide is aimed at helping CarrierWave users transition to Shrine, and it
6
6
  consists of three parts:
7
7
 
8
8
  1. Explanation of the key differences in design between CarrierWave and Shrine
9
- 2. Instructions how to migrate and existing app that uses CarrierWave to Shrine
9
+ 2. Instructions how to migrate an existing app that uses CarrierWave to Shrine
10
10
  3. Extensive reference of CarrierWave's interface with Shrine equivalents
11
11
 
12
12
  ## Overview
@@ -159,7 +159,7 @@ require "image_processing/mini_magick"
159
159
  class ImageUploader < Shrine
160
160
  plugin :derivatives
161
161
 
162
- Attacher.derivatives_processor do |original|
162
+ Attacher.derivatives do |original|
163
163
  magick = ImageProcessing::MiniMagick.source(original)
164
164
 
165
165
  {
@@ -268,18 +268,24 @@ Files] guide explains this setup in more detail.
268
268
  ## Migrating from CarrierWave
269
269
 
270
270
  You have an existing app using CarrierWave and you want to transfer it to
271
- Shrine. Let's assume we have a `Photo` model with the "image" attachment. First
272
- we need to create the `image_data` column for Shrine:
271
+ Shrine. Let's assume we have a `Photo` model with the "image" attachment.
272
+
273
+ ### 1. Add Shrine column
274
+
275
+ First we need to create the `image_data` column for Shrine:
273
276
 
274
277
  ```rb
275
278
  add_column :photos, :image_data, :text # or :json or :jsonb if supported
276
279
  ```
277
280
 
278
- Afterwards we need to make new uploads write to the `image_data` column. This
279
- can be done by including the below module to all models that have CarrierWave
280
- attachments:
281
+ ### 2. Dual write
282
+
283
+ Next, we need to make new CarrierWave attachments write to the
284
+ `image_data` column. This can be done by including the below module to all
285
+ models that have CarrierWave attachments:
281
286
 
282
287
  ```rb
288
+ # config/initializers/shrine.rb (Rails)
283
289
  require "shrine"
284
290
 
285
291
  Shrine.storages = {
@@ -289,8 +295,7 @@ Shrine.storages = {
289
295
 
290
296
  Shrine.plugin :model
291
297
  Shrine.plugin :derivatives
292
- ```
293
- ```rb
298
+
294
299
  module CarrierwaveShrineSynchronization
295
300
  def self.included(model)
296
301
  model.before_save do
@@ -302,13 +307,13 @@ module CarrierwaveShrineSynchronization
302
307
 
303
308
  def write_shrine_data(name)
304
309
  uploader = send(name)
305
- attacher = Shrine::Attacher.form_model(self, name)
310
+ attacher = Shrine::Attacher.from_model(self, name)
306
311
 
307
312
  if read_attribute(name).present?
308
313
  attacher.set shrine_file(uploader)
309
314
 
310
- uploader.versions.each do |name, version|
311
- attacher.merge_derivatives(name => shrine_file(version))
315
+ uploader.versions.each do |version_name, version|
316
+ attacher.merge_derivatives(version_name => shrine_file(version))
312
317
  end
313
318
  else
314
319
  attacher.set nil
@@ -317,19 +322,22 @@ module CarrierwaveShrineSynchronization
317
322
 
318
323
  private
319
324
 
320
- # If you'll be using `:prefix` on your Shrine storage, make sure to
321
- # subtract it from the path assigned as `:id`.
322
325
  def shrine_file(uploader)
323
326
  name = uploader.mounted_as
324
327
  filename = read_attribute(name)
325
- path = uploader.store_path(filename)
328
+ location = uploader.store_path(filename)
329
+ location = location.sub(%r{^#{storage.prefix}/}, "") if storage.prefix
326
330
 
327
331
  Shrine.uploaded_file(
328
332
  storage: :store,
329
- id: path,
333
+ id: location,
330
334
  metadata: { "filename" => filename },
331
335
  )
332
336
  end
337
+
338
+ def storage
339
+ Shrine.storages[:store]
340
+ end
333
341
  end
334
342
  ```
335
343
  ```rb
@@ -340,20 +348,27 @@ end
340
348
  ```
341
349
 
342
350
  After you deploy this code, the `image_data` column should now be successfully
343
- synchronized with new attachments. Next step is to run a script which writes
344
- all existing CarrierWave attachments to `image_data`:
351
+ synchronized with new attachments.
352
+
353
+ ### 3. Data migration
354
+
355
+ Next step is to run a script which writes all existing CarrierWave attachments
356
+ to `image_data`:
345
357
 
346
358
  ```rb
347
359
  Photo.find_each do |photo|
348
- Photo.uploaders.each_key { |name| photo.write_shrine_data(name) }
360
+ photo.write_shrine_data(:image)
349
361
  photo.save!
350
362
  end
351
363
  ```
352
364
 
365
+ ### 4. Rewrite code
366
+
353
367
  Now you should be able to rewrite your application so that it uses Shrine
354
- instead of CarrierWave, using equivalent Shrine storages. For help with
355
- translating the code from CarrierWave to Shrine, you can consult the reference
356
- below.
368
+ instead of CarrierWave (you can consult the reference in the next section). You
369
+ can remove the `CarrierwaveShrineSynchronization` module as well.
370
+
371
+ ### 5. Backill metadata
357
372
 
358
373
  You'll notice that Shrine metadata will be absent from the migrated files'
359
374
  data. You can run a script that will fill in any missing metadata defined in
@@ -363,11 +378,20 @@ your Shrine uploader:
363
378
  Shrine.plugin :refresh_metadata
364
379
 
365
380
  Photo.find_each do |photo|
366
- photo.image_attacher.refresh_metadata!
367
- photo.save
381
+ attacher = photo.image_attacher
382
+ attacher.refresh_metadata!
383
+ attacher.atomic_persist
368
384
  end
369
385
  ```
370
386
 
387
+ ### 6. Remove CarrierWave column
388
+
389
+ If everything is looking good, we can remove the CarrierWave column:
390
+
391
+ ```rb
392
+ remove_column :photos, :image
393
+ ```
394
+
371
395
  ## CarrierWave to Shrine direct mapping
372
396
 
373
397
  ### `CarrierWave::Uploader::Base`
@@ -395,7 +419,7 @@ Processing is defined by using the `derivatives` plugin:
395
419
  class ImageUploader < Shrine
396
420
  plugin :derivatives
397
421
 
398
- Attacher.derivatives_processor do |original|
422
+ Attacher.derivatives do |original|
399
423
  magick = ImageProcessing::MiniMagick.source(image)
400
424
 
401
425
  {
@@ -455,16 +479,25 @@ photo.image.original_filename #=> "avatar.jpg"
455
479
 
456
480
  #### `#store_dir`, `#cache_dir`
457
481
 
458
- Shrine here provides a `#generate_location` method, which is triggered for all
459
- storages:
482
+ Shrine here provides a single `#generate_location` method that's triggered for
483
+ all storages:
460
484
 
461
485
  ```rb
462
486
  class ImageUploader < Shrine
463
- def generate_location(io, record: nil, **)
464
- "#{record.class}/#{record.id}/#{io.original_filename}"
487
+ def generate_location(io, record: nil, name: nil, **)
488
+ [ storage_key,
489
+ record && record.class.name.underscore,
490
+ record && record.id,
491
+ super,
492
+ io.original_filename ].compact.join("/")
465
493
  end
466
494
  end
467
495
  ```
496
+ ```
497
+ cache/user/123/2feff8c724e7ce17/nature.jpg
498
+ store/user/456/7f99669fde1e01fc/kitten.jpg
499
+ ...
500
+ ```
468
501
 
469
502
  You might also want to use the `pretty_location` plugin for automatically
470
503
  generating an organized folder structure.
@@ -477,8 +510,8 @@ For default URLs you can use the `default_url` plugin:
477
510
  class ImageUploader < Shrine
478
511
  plugin :default_url
479
512
 
480
- Attacher.default_url do |options|
481
- "/attachments/#{name}/default.jpg"
513
+ Attacher.default_url do |derivative: nil, **|
514
+ "/fallbacks/#{derivative || "original"}.jpg"
482
515
  end
483
516
  end
484
517
  ```
@@ -499,7 +532,7 @@ class ImageUploader < Shrine
499
532
  end
500
533
  ```
501
534
 
502
- #### `#blacklist_mime_type_pattern`, `#whitelist_mime_type_pattern`, `#content_type_whitelist`, `#content_type_blacklist`
535
+ #### `#content_type_whitelist`, `#content_type_blacklist`
503
536
 
504
537
  In Shrine, MIME type whitelisting/blacklisting is part of validations, and is
505
538
  provided by the `validation_helpers` plugin, though it doesn't support regexes:
@@ -515,6 +548,17 @@ class ImageUploader < Shrine
515
548
  end
516
549
  ```
517
550
 
551
+ Make sure to also load the `determine_mime_type` plugin to detect MIME type
552
+ from file content.
553
+
554
+ ```rb
555
+ # Gemfile
556
+ gem "mimemagic"
557
+ ```
558
+ ```rb
559
+ Shrine.plugin :determine_mime_type, analyzer: :mimemagic
560
+ ```
561
+
518
562
  #### `#size_range`
519
563
 
520
564
  In Shrine file size validations are typically done using the
@@ -622,7 +666,7 @@ shows what are Shrine's equivalents.
622
666
 
623
667
  #### `root`, `base_path`, `permissions`, `directory_permissions`
624
668
 
625
- In Shrine these are configured on the FileSystem storage directly.
669
+ In Shrine these are configured on the `FileSystem` storage directly.
626
670
 
627
671
  #### `storage`, `storage_engines`
628
672