shrine 3.0.1 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
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