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.
- 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
|
|