shrine 3.0.1 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +82 -0
- data/LICENSE.txt +1 -1
- data/README.md +15 -5
- data/doc/advantages.md +33 -16
- data/doc/attacher.md +2 -2
- data/doc/carrierwave.md +78 -34
- data/doc/changing_derivatives.md +39 -39
- data/doc/design.md +134 -85
- data/doc/direct_s3.md +1 -0
- data/doc/external/articles.md +57 -45
- data/doc/external/extensions.md +41 -35
- data/doc/external/misc.md +23 -8
- data/doc/getting_started.md +177 -112
- data/doc/metadata.md +79 -43
- data/doc/multiple_files.md +6 -4
- data/doc/paperclip.md +119 -42
- data/doc/plugins/activerecord.md +1 -1
- data/doc/plugins/add_metadata.md +112 -35
- data/doc/plugins/atomic_helpers.md +41 -3
- data/doc/plugins/backgrounding.md +12 -2
- data/doc/plugins/column.md +36 -7
- data/doc/plugins/data_uri.md +2 -2
- data/doc/plugins/default_url.md +6 -3
- data/doc/plugins/derivation_endpoint.md +26 -28
- data/doc/plugins/derivatives.md +238 -171
- data/doc/plugins/determine_mime_type.md +2 -2
- data/doc/plugins/download_endpoint.md +5 -5
- data/doc/plugins/dynamic_storage.md +1 -1
- data/doc/plugins/form_assign.md +5 -5
- data/doc/plugins/included.md +25 -5
- data/doc/plugins/infer_extension.md +11 -2
- data/doc/plugins/instrumentation.md +1 -1
- data/doc/plugins/metadata_attributes.md +22 -10
- data/doc/plugins/mirroring.md +1 -1
- data/doc/plugins/persistence.md +11 -1
- data/doc/plugins/refresh_metadata.md +5 -4
- data/doc/plugins/remote_url.md +8 -3
- data/doc/plugins/remove_invalid.md +9 -1
- data/doc/plugins/signature.md +11 -2
- data/doc/plugins/store_dimensions.md +12 -2
- data/doc/plugins/type_predicates.md +96 -0
- data/doc/plugins/upload_endpoint.md +7 -11
- data/doc/plugins/upload_options.md +1 -1
- data/doc/plugins/url_options.md +4 -4
- data/doc/plugins/validation.md +14 -4
- data/doc/plugins/validation_helpers.md +3 -3
- data/doc/plugins/versions.md +7 -7
- data/doc/processing.md +290 -127
- data/doc/refile.md +39 -18
- data/doc/release_notes/2.19.0.md +1 -1
- data/doc/release_notes/2.8.0.md +1 -1
- data/doc/release_notes/3.0.0.md +1 -1
- data/doc/release_notes/3.0.1.md +4 -0
- data/doc/release_notes/3.1.0.md +73 -0
- data/doc/release_notes/3.2.0.md +96 -0
- data/doc/release_notes/3.2.1.md +31 -0
- data/doc/release_notes/3.2.2.md +14 -0
- data/doc/release_notes/3.3.0.md +105 -0
- data/doc/securing_uploads.md +3 -3
- data/doc/storage/file_system.md +1 -1
- data/doc/storage/memory.md +19 -0
- data/doc/storage/s3.md +105 -82
- data/doc/testing.md +2 -2
- data/doc/upgrading_to_3.md +97 -49
- data/doc/validation.md +3 -2
- data/lib/shrine.rb +8 -8
- data/lib/shrine/attacher.rb +24 -14
- data/lib/shrine/attachment.rb +5 -5
- data/lib/shrine/plugins.rb +22 -0
- data/lib/shrine/plugins/activerecord.rb +1 -1
- data/lib/shrine/plugins/add_metadata.rb +18 -7
- data/lib/shrine/plugins/backgrounding.rb +2 -2
- data/lib/shrine/plugins/default_storage.rb +6 -6
- data/lib/shrine/plugins/default_url.rb +1 -1
- data/lib/shrine/plugins/derivation_endpoint.rb +12 -7
- data/lib/shrine/plugins/derivatives.rb +61 -29
- data/lib/shrine/plugins/determine_mime_type.rb +3 -3
- data/lib/shrine/plugins/entity.rb +6 -6
- data/lib/shrine/plugins/mirroring.rb +8 -8
- data/lib/shrine/plugins/model.rb +3 -3
- data/lib/shrine/plugins/presign_endpoint.rb +16 -4
- data/lib/shrine/plugins/pretty_location.rb +1 -1
- data/lib/shrine/plugins/processing.rb +1 -1
- data/lib/shrine/plugins/refresh_metadata.rb +2 -2
- data/lib/shrine/plugins/remote_url.rb +3 -3
- data/lib/shrine/plugins/remove_attachment.rb +5 -0
- data/lib/shrine/plugins/remove_invalid.rb +10 -5
- data/lib/shrine/plugins/sequel.rb +1 -1
- data/lib/shrine/plugins/signature.rb +7 -6
- data/lib/shrine/plugins/store_dimensions.rb +22 -11
- data/lib/shrine/plugins/type_predicates.rb +113 -0
- data/lib/shrine/plugins/upload_endpoint.rb +10 -5
- data/lib/shrine/plugins/upload_options.rb +2 -2
- data/lib/shrine/plugins/url_options.rb +2 -2
- data/lib/shrine/plugins/validation.rb +9 -7
- data/lib/shrine/storage/linter.rb +4 -4
- data/lib/shrine/storage/memory.rb +5 -3
- data/lib/shrine/storage/s3.rb +117 -38
- data/lib/shrine/uploaded_file.rb +0 -1
- data/lib/shrine/version.rb +2 -2
- data/shrine.gemspec +7 -8
- metadata +25 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8cfa59ed1f6143ee9298ede17eeda07dba85f0f9c3309a5b7a9e7f6c41399f29
|
4
|
+
data.tar.gz: 67a64a3a4f40c34797ca04279af73829acf4071eb118f78addefdbaa15e048da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e87a3dbb80a304f8af559b9c3d4e8badf8e47e4377afd74fe08d570042d65358d44878c4a0366fa3cded98fe166083275e86c61f3b51d28d35e070e0233dea35
|
7
|
+
data.tar.gz: 83c93e76bf5513ab317ccabbdda86ce90f760e7b898dc9f40036af3e7ec915f48e55bd6f8efcf8661dacea672ce6b24b450db217815b062881169c8c90fd0cd3
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,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)
|
data/LICENSE.txt
CHANGED
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 [
|
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
|
-
|
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
|
-
```
|
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
|
-
[
|
148
|
-
[on-the-fly]: https://shrinerb.com/docs/getting-started#
|
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
|
data/doc/advantages.md
CHANGED
@@ -93,7 +93,7 @@ low-level abstractions that give you the flexibility to build your own flow.
|
|
93
93
|
```rb
|
94
94
|
uploaded_file = ImageUploader.upload(image, :store) # metadata extraction, upload location generation
|
95
95
|
uploaded_file.id #=> "44ccafc10ce6a4ff22829e8f579ee6b9.jpg"
|
96
|
-
|
96
|
+
uploaded_file.metadata #=> { ... extracted metadata ... }
|
97
97
|
|
98
98
|
data = uploaded_file.to_json # serialization
|
99
99
|
# ...
|
@@ -157,21 +157,21 @@ end
|
|
157
157
|
|
158
158
|
## Processing
|
159
159
|
|
160
|
-
Most file attachment libraries
|
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 [
|
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.
|
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.
|
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
|
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
|
-
|
305
|
-
|
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
|
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
|
-
|
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
|
-
|
315
|
-
|
316
|
-
|
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
|
data/doc/attacher.md
CHANGED
@@ -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)
|
data/doc/carrierwave.md
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
---
|
2
|
-
title:
|
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
|
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.
|
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.
|
272
|
-
|
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
|
-
|
279
|
-
|
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.
|
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 |
|
311
|
-
attacher.merge_derivatives(
|
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
|
-
|
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:
|
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.
|
344
|
-
|
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
|
-
|
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
|
355
|
-
|
356
|
-
|
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
|
367
|
-
|
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.
|
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
|
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
|
-
|
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 |
|
481
|
-
"/
|
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
|
-
####
|
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
|
|