shrine 3.0.1 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of shrine might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/LICENSE.txt +1 -1
- data/README.md +7 -2
- data/doc/advantages.md +29 -12
- data/doc/carrierwave.md +54 -22
- data/doc/changing_derivatives.md +39 -39
- data/doc/getting_started.md +63 -58
- data/doc/multiple_files.md +5 -3
- data/doc/paperclip.md +92 -33
- data/doc/plugins/activerecord.md +1 -1
- data/doc/plugins/data_uri.md +2 -2
- data/doc/plugins/derivation_endpoint.md +26 -28
- data/doc/plugins/derivatives.md +170 -142
- data/doc/plugins/determine_mime_type.md +2 -2
- data/doc/plugins/infer_extension.md +2 -2
- data/doc/plugins/instrumentation.md +1 -1
- data/doc/plugins/metadata_attributes.md +21 -10
- data/doc/plugins/persistence.md +1 -0
- data/doc/plugins/refresh_metadata.md +5 -4
- data/doc/plugins/remote_url.md +2 -2
- data/doc/plugins/signature.md +11 -2
- data/doc/plugins/store_dimensions.md +2 -2
- data/doc/plugins/upload_endpoint.md +7 -11
- data/doc/plugins/validation_helpers.md +3 -3
- data/doc/processing.md +5 -5
- data/doc/refile.md +30 -9
- data/doc/release_notes/2.19.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/securing_uploads.md +1 -1
- data/doc/storage/file_system.md +1 -1
- data/doc/storage/s3.md +1 -5
- data/doc/upgrading_to_3.md +4 -2
- data/doc/validation.md +3 -2
- data/lib/shrine.rb +1 -2
- data/lib/shrine/attacher.rb +4 -4
- data/lib/shrine/attachment.rb +3 -3
- data/lib/shrine/plugins/add_metadata.rb +1 -5
- data/lib/shrine/plugins/default_storage.rb +6 -6
- data/lib/shrine/plugins/derivatives.rb +4 -3
- data/lib/shrine/plugins/signature.rb +7 -6
- data/lib/shrine/plugins/store_dimensions.rb +18 -9
- data/lib/shrine/uploaded_file.rb +0 -1
- data/lib/shrine/version.rb +2 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 30bd30989579217202b2c51b9a00abe778af7cbab75fc9df78052bc074ce9405
|
4
|
+
data.tar.gz: 5c718df903c203e06ea44afa9c9017fa2cf01a8924c99e86a87be52f52ce0233
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27f896211caba27686d5988750ce214ec0b31e70e9bbcf8a7d325952a5eee2e4c3293d539bb3074d4384964723bda09edd1acfcdcd387d82a4ef7373ff5787f0
|
7
|
+
data.tar.gz: 3d06d57d2eb1fee1cada71dfa4092a23c4b0bf4d5df8cf76e2fbf2eb4eaf5c9477f333ef241772d917456ebfb3067ad0ce7adc6becc49e15c9129720842cd5b3
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
## 3.1.0 (2019-11-15) [[release notes]](https://shrinerb.com/docs/release_notes/3.1.0)
|
2
|
+
|
3
|
+
* `default_storage` – Coerce storage key to symbol in `Attacher#cache_key` & `Attacher#store_key` (@janko)
|
4
|
+
|
5
|
+
* `core` – Coerce storage key to symbol in `Attacher#cache_key` & `Attacher#store_key` (@janko)
|
6
|
+
|
7
|
+
* `add_metadata` – Define metadata methods only for the target uploader class (@janko)
|
8
|
+
|
9
|
+
* `derivatives` – Add `:storage` option to `Attacher#create_derivatives` (@janko)
|
10
|
+
|
11
|
+
* `store_dimensions` – Propagate exceptions on loading `ruby-vips` in `:vips` analyzer (@janko)
|
12
|
+
|
13
|
+
* `signature` – Allow skipping rewinding by passing `rewind: false` to `Shrine.signature` (@janko)
|
14
|
+
|
15
|
+
* `derivatives` – Add `Attacher.derivatives` alias for `Attacher.derivatives_processor` (@janko)
|
16
|
+
|
1
17
|
## 3.0.1 (2019-10-17) [[release notes]](https://shrinerb.com/docs/release_notes/3.0.1)
|
2
18
|
|
3
19
|
* `metadata_attributes` – Fix exception being raised when there is no attached file (@janko)
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
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
|
@@ -12,7 +14,9 @@ Shrine is a toolkit for handling file attachments in Ruby applications. Some hig
|
|
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
|
|
@@ -133,6 +137,7 @@ mailing lists is expected to follow the [Shrine code of conduct][CoC].
|
|
133
137
|
The gem is available as open source under the terms of the [MIT License].
|
134
138
|
|
135
139
|
[Shrine]: https://shrinerb.com
|
140
|
+
[Advantages of Shrine]: https://shrinerb.com/docs/advantages
|
136
141
|
[plugin system]: https://shrinerb.com/docs/getting-started#plugin-system
|
137
142
|
[Retrieving Uploads]: https://shrinerb.com/docs/retrieving-uploads
|
138
143
|
[FileSystem]: https://shrinerb.com/docs/storage/file-system
|
data/doc/advantages.md
CHANGED
@@ -171,7 +171,7 @@ 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/carrierwave.md
CHANGED
@@ -6,7 +6,7 @@ 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
|
@@ -340,20 +345,27 @@ end
|
|
340
345
|
```
|
341
346
|
|
342
347
|
After you deploy this code, the `image_data` column should now be successfully
|
343
|
-
synchronized with new attachments.
|
344
|
-
|
348
|
+
synchronized with new attachments.
|
349
|
+
|
350
|
+
### 3. Data migration
|
351
|
+
|
352
|
+
Next step is to run a script which writes all existing CarrierWave attachments
|
353
|
+
to `image_data`:
|
345
354
|
|
346
355
|
```rb
|
347
356
|
Photo.find_each do |photo|
|
348
|
-
|
357
|
+
photo.write_shrine_data(:image)
|
349
358
|
photo.save!
|
350
359
|
end
|
351
360
|
```
|
352
361
|
|
362
|
+
### 4. Rewrite code
|
363
|
+
|
353
364
|
Now you should be able to rewrite your application so that it uses Shrine
|
354
|
-
instead of CarrierWave
|
355
|
-
|
356
|
-
|
365
|
+
instead of CarrierWave (you can consult the reference in the next section). You
|
366
|
+
can remove the `CarrierwaveShrineSynchronization` module as well.
|
367
|
+
|
368
|
+
### 5. Backill metadata
|
357
369
|
|
358
370
|
You'll notice that Shrine metadata will be absent from the migrated files'
|
359
371
|
data. You can run a script that will fill in any missing metadata defined in
|
@@ -363,11 +375,20 @@ your Shrine uploader:
|
|
363
375
|
Shrine.plugin :refresh_metadata
|
364
376
|
|
365
377
|
Photo.find_each do |photo|
|
366
|
-
photo.image_attacher
|
367
|
-
|
378
|
+
attacher = photo.image_attacher
|
379
|
+
attacher.refresh_metadata!
|
380
|
+
attacher.atomic_persist
|
368
381
|
end
|
369
382
|
```
|
370
383
|
|
384
|
+
### 6. Remove CarrierWave column
|
385
|
+
|
386
|
+
If everything is looking good, we can remove the CarrierWave column:
|
387
|
+
|
388
|
+
```rb
|
389
|
+
remove_column :photos, :image
|
390
|
+
```
|
391
|
+
|
371
392
|
## CarrierWave to Shrine direct mapping
|
372
393
|
|
373
394
|
### `CarrierWave::Uploader::Base`
|
@@ -395,7 +416,7 @@ Processing is defined by using the `derivatives` plugin:
|
|
395
416
|
class ImageUploader < Shrine
|
396
417
|
plugin :derivatives
|
397
418
|
|
398
|
-
Attacher.
|
419
|
+
Attacher.derivatives do |original|
|
399
420
|
magick = ImageProcessing::MiniMagick.source(image)
|
400
421
|
|
401
422
|
{
|
@@ -499,7 +520,7 @@ class ImageUploader < Shrine
|
|
499
520
|
end
|
500
521
|
```
|
501
522
|
|
502
|
-
####
|
523
|
+
#### `#content_type_whitelist`, `#content_type_blacklist`
|
503
524
|
|
504
525
|
In Shrine, MIME type whitelisting/blacklisting is part of validations, and is
|
505
526
|
provided by the `validation_helpers` plugin, though it doesn't support regexes:
|
@@ -515,6 +536,17 @@ class ImageUploader < Shrine
|
|
515
536
|
end
|
516
537
|
```
|
517
538
|
|
539
|
+
Make sure to also load the `determine_mime_type` plugin to detect MIME type
|
540
|
+
from file content.
|
541
|
+
|
542
|
+
```rb
|
543
|
+
# Gemfile
|
544
|
+
gem "mimemagic"
|
545
|
+
```
|
546
|
+
```rb
|
547
|
+
Shrine.plugin :determine_mime_type, analyzer: :mimemagic
|
548
|
+
```
|
549
|
+
|
518
550
|
#### `#size_range`
|
519
551
|
|
520
552
|
In Shrine file size validations are typically done using the
|
data/doc/changing_derivatives.md
CHANGED
@@ -42,7 +42,7 @@ gem "image_processing", "~> 1.8"
|
|
42
42
|
require "image_processing/mini_magick"
|
43
43
|
|
44
44
|
class ImageUploader < Shrine
|
45
|
-
Attacher.
|
45
|
+
Attacher.derivatives do |original|
|
46
46
|
magick = ImageProcessing::MiniMagick.source(original)
|
47
47
|
|
48
48
|
# generate the thumbnails you want here
|
@@ -93,16 +93,16 @@ now you want to reprocess them for existing attachments.*
|
|
93
93
|
Let's assume we've made the following change and have deployed it to production:
|
94
94
|
|
95
95
|
```diff
|
96
|
-
Attacher.
|
97
|
-
|
96
|
+
Attacher.derivatives do |original|
|
97
|
+
magick = ImageProcessing::MiniMagick.source(original)
|
98
98
|
+ .saver(quality: 85)
|
99
99
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
end
|
100
|
+
{
|
101
|
+
small: magick.resize_to_limit!(300, 300),
|
102
|
+
medium: magick.resize_to_limit!(500, 500),
|
103
|
+
large: magick.resize_to_limit!(800, 800),
|
104
|
+
}
|
105
|
+
end
|
106
106
|
```
|
107
107
|
|
108
108
|
We can now run the following script to reprocess derivatives for all existing
|
@@ -139,16 +139,16 @@ you want to reprocess them for existing attachments.*
|
|
139
139
|
Let's assume we've made a following change and have deployed it to production:
|
140
140
|
|
141
141
|
```diff
|
142
|
-
Attacher.
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
-
|
148
|
-
+
|
149
|
-
|
150
|
-
|
151
|
-
end
|
142
|
+
Attacher.derivatives do |original|
|
143
|
+
magick = ImageProcessing::MiniMagick.source(original)
|
144
|
+
|
145
|
+
{
|
146
|
+
small: magick.resize_to_limit!(300, 300),
|
147
|
+
- medium: magick.resize_to_limit!(500, 500),
|
148
|
+
+ medium: magick.resize_to_limit!(600, 600),
|
149
|
+
large: magick.resize_to_limit!(800, 800),
|
150
|
+
}
|
151
|
+
end
|
152
152
|
```
|
153
153
|
|
154
154
|
We can now run the following script to reprocess the derivative for all
|
@@ -189,16 +189,16 @@ you want to add it to existing attachments.*
|
|
189
189
|
Let's assume we've made a following change and have deployed it to production:
|
190
190
|
|
191
191
|
```diff
|
192
|
-
Attacher.
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
+
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
end
|
192
|
+
Attacher.derivatives do |original|
|
193
|
+
magick = ImageProcessing::MiniMagick.source(original)
|
194
|
+
|
195
|
+
{
|
196
|
+
+ square: magick.resize_to_fill!(150, 150),
|
197
|
+
small: magick.resize_to_limit!(300, 300),
|
198
|
+
medium: magick.resize_to_limit!(600, 600),
|
199
|
+
large: magick.resize_to_limit!(800, 800),
|
200
|
+
}
|
201
|
+
end
|
202
202
|
```
|
203
203
|
|
204
204
|
We can now run following script to add the new derivative for all existing
|
@@ -239,16 +239,16 @@ existing attachments.*
|
|
239
239
|
Let's assume we've made the following change and have deployed it to production:
|
240
240
|
|
241
241
|
```diff
|
242
|
-
Attacher.
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
end
|
242
|
+
Attacher.derivatives do |original|
|
243
|
+
magick = ImageProcessing::MiniMagick.source(original)
|
244
|
+
|
245
|
+
{
|
246
|
+
- square: magick.resize_to_fill!(150, 150),
|
247
|
+
small: magick.resize_to_limit!(300, 300),
|
248
|
+
medium: magick.resize_to_limit!(600, 600),
|
249
|
+
large: magick.resize_to_limit!(800, 800),
|
250
|
+
}
|
251
|
+
end
|
252
252
|
```
|
253
253
|
|
254
254
|
We can now run following script to remove the unused derivative for all
|
data/doc/getting_started.md
CHANGED
@@ -50,7 +50,7 @@ class AddImageDataToPhotos < ActiveRecord::Migration
|
|
50
50
|
end
|
51
51
|
```
|
52
52
|
<!--Rails-->
|
53
|
-
```
|
53
|
+
```
|
54
54
|
$ rails generate migration add_image_data_to_photos image_data:text
|
55
55
|
```
|
56
56
|
<!--END_DOCUSAURUS_CODE_TABS-->
|
@@ -186,8 +186,8 @@ s3_options = {
|
|
186
186
|
}
|
187
187
|
|
188
188
|
Shrine.storages = {
|
189
|
-
cache: Shrine::Storage::S3.new(prefix: "cache", **s3_options),
|
190
|
-
store: Shrine::Storage::S3.new(**s3_options),
|
189
|
+
cache: Shrine::Storage::S3.new(prefix: "cache", **s3_options), # temporary
|
190
|
+
store: Shrine::Storage::S3.new(**s3_options), # permanent
|
191
191
|
}
|
192
192
|
```
|
193
193
|
|
@@ -254,15 +254,17 @@ uploader.upload(io, upload_options: { acl: "public-read" }) # add options to Sto
|
|
254
254
|
|
255
255
|
Shrine is able to upload any IO-like object that implement methods [`#read`],
|
256
256
|
[`#rewind`], [`#eof?`] and [`#close`] whose behaviour matches the [`IO`] class.
|
257
|
-
This includes
|
257
|
+
This includes but is not limited to the following objects:
|
258
258
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
259
|
+
* `File`
|
260
|
+
* `Tempfile`
|
261
|
+
* `StringIO`
|
262
|
+
* `ActionDispatch::Http::UploadedFile` (Rails form upload)
|
263
|
+
* `Shrine::RackFile` ([`rack_file`][rack_file plugin] plugin)
|
264
|
+
* `Shrine::DataFile` ([`data_uri`][data_uri plugin] plugin)
|
265
|
+
* `Shrine::UploadedFile`
|
266
|
+
* `Down::ChunkedIO` ([Down] gem)
|
267
|
+
* ...
|
266
268
|
|
267
269
|
```rb
|
268
270
|
uploader.upload File.open("/path/to/file", binmode: true) # upload from disk
|
@@ -278,7 +280,15 @@ uploader.upload Shrine::UploadedFile.new(...) # upload from Shrine
|
|
278
280
|
|
279
281
|
The `Shrine::UploadedFile` object represents the file that was uploaded to a
|
280
282
|
storage, and it's what's returned from `Shrine#upload` or when retrieving a
|
281
|
-
record [attachment].
|
283
|
+
record [attachment].
|
284
|
+
|
285
|
+
```rb
|
286
|
+
uploader.upload(file) #=> #<Shrine::UploadedFile ...> (uploader)
|
287
|
+
photo.image #=> #<Shrine::UploadedFile ...> (attachment)
|
288
|
+
attacher.file #=> #<Shrine::UploadedFile ...> (attacher)
|
289
|
+
```
|
290
|
+
|
291
|
+
An uploaded file object contains the following data:
|
282
292
|
|
283
293
|
| Key | Description |
|
284
294
|
| :------- | :---------- |
|
@@ -287,13 +297,12 @@ record [attachment]. It contains the following data:
|
|
287
297
|
| `metadata` | file [metadata] that was extracted before upload |
|
288
298
|
|
289
299
|
```rb
|
290
|
-
uploaded_file = uploader.upload(file)
|
291
300
|
uploaded_file #=> #<Shrine::UploadedFile id="949sdjg834.jpg" storage=:store metadata={...}>
|
292
301
|
|
293
|
-
uploaded_file.id
|
294
|
-
uploaded_file.storage_key
|
295
|
-
uploaded_file.storage
|
296
|
-
uploaded_file.metadata
|
302
|
+
uploaded_file.id #=> "949sdjg834.jpg"
|
303
|
+
uploaded_file.storage_key #=> :store
|
304
|
+
uploaded_file.storage #=> #<Shrine::Storage::S3>
|
305
|
+
uploaded_file.metadata #=> {...}
|
297
306
|
```
|
298
307
|
|
299
308
|
It comes with many convenient methods that delegate to the storage:
|
@@ -341,7 +350,7 @@ The easiest way to attach files is with the `Shrine::Attachment` module:
|
|
341
350
|
```rb
|
342
351
|
class Photo < Sequel::Model # ActiveRecord::Base
|
343
352
|
include ImageUploader::Attachment.new(:image) #
|
344
|
-
include ImageUploader::Attachment[:image] # use
|
353
|
+
include ImageUploader::Attachment[:image] # use your preferred syntax
|
345
354
|
include ImageUploader::Attachment(:image) #
|
346
355
|
end
|
347
356
|
```
|
@@ -364,7 +373,7 @@ that attachments are deleted when the record is destroyed.
|
|
364
373
|
photo.image #=> nil
|
365
374
|
|
366
375
|
# the assigned file is cached to temporary storage and written to `image_data` column
|
367
|
-
photo.image = File.open("waterfall.jpg")
|
376
|
+
photo.image = File.open("waterfall.jpg", "rb")
|
368
377
|
photo.image #=> #<Shrine::UploadedFile ...>
|
369
378
|
photo.image_url #=> "/uploads/cache/0sdfllasfi842.jpg"
|
370
379
|
photo.image_data #=> '{"id":"0sdfllasfi842.jpg","storage":"cache","metadata":{...}}'
|
@@ -408,12 +417,10 @@ attacher.url # equivalent to `photo.image_url`
|
|
408
417
|
```
|
409
418
|
|
410
419
|
The attacher is what drives attaching files to model instances; you can use it
|
411
|
-
as a more explicit alternative to models' attachment interface, or
|
412
|
-
|
420
|
+
as a more explicit alternative to models' attachment interface, or when you
|
421
|
+
need something that's not available through the attachment methods.
|
413
422
|
|
414
|
-
|
415
|
-
attacher uses, or upload files directly to permanent storage. See the [Using
|
416
|
-
Attacher] guide for more details.
|
423
|
+
See [Using Attacher] guide for more details.
|
417
424
|
|
418
425
|
### Temporary storage
|
419
426
|
|
@@ -424,18 +431,18 @@ files go straight to permanent storage:
|
|
424
431
|
```rb
|
425
432
|
Shrine.plugin :model, cache: false
|
426
433
|
```
|
427
|
-
<!--DOCUSAURUS_CODE_TABS-->
|
428
|
-
<!--Attachment-->
|
429
434
|
```rb
|
430
|
-
photo.image = File.open("waterfall.jpg")
|
435
|
+
photo.image = File.open("waterfall.jpg", "rb")
|
431
436
|
photo.image.storage_key #=> :store
|
432
437
|
```
|
433
|
-
|
438
|
+
|
439
|
+
If you're using the attacher directly, you can just use `Attacher#attach`
|
440
|
+
instead of `Attacher#assign`:
|
441
|
+
|
434
442
|
```rb
|
435
|
-
attacher.attach File.open("waterfall.jpg")
|
443
|
+
attacher.attach File.open("waterfall.jpg", "rb")
|
436
444
|
attacher.file.storage_key #=> :store
|
437
445
|
```
|
438
|
-
<!--END_DOCUSAURUS_CODE_TABS-->
|
439
446
|
|
440
447
|
## Plugin system
|
441
448
|
|
@@ -519,7 +526,7 @@ For image processing, it's recommended to use the **[ImageProcessing]** gem,
|
|
519
526
|
which is a high-level wrapper for processing with
|
520
527
|
[MiniMagick][ImageProcessing::MiniMagick] and [libvips][ImageProcessing::Vips].
|
521
528
|
|
522
|
-
```
|
529
|
+
```
|
523
530
|
$ brew install imagemagick vips
|
524
531
|
```
|
525
532
|
|
@@ -539,7 +546,7 @@ Shrine.plugin :derivatives
|
|
539
546
|
require "image_processing/mini_magick"
|
540
547
|
|
541
548
|
class ImageUploader < Shrine
|
542
|
-
Attacher.
|
549
|
+
Attacher.derivatives do |original|
|
543
550
|
magick = ImageProcessing::MiniMagick.source(original)
|
544
551
|
|
545
552
|
{
|
@@ -580,12 +587,9 @@ documentation and the [File Processing] guide.
|
|
580
587
|
### Processing on-the-fly
|
581
588
|
|
582
589
|
On-the-fly processing is provided by the
|
583
|
-
[`derivation_endpoint`][derivation_endpoint plugin] plugin.
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
To set it up, we mount the Rack app in our router on a chosen path prefix,
|
588
|
-
configure the plugin with a secret key and that path prefix, and define
|
590
|
+
[`derivation_endpoint`][derivation_endpoint plugin] plugin. To set it up, we
|
591
|
+
configure the plugin with a secret key and a path prefix, [mount][Mounting
|
592
|
+
Endpoints] its Rack app in our routes on the configured path prefix, and define
|
589
593
|
processing we want to perform:
|
590
594
|
|
591
595
|
```rb
|
@@ -593,25 +597,24 @@ processing we want to perform:
|
|
593
597
|
gem "image_processing", "~> 1.8"
|
594
598
|
```
|
595
599
|
```rb
|
596
|
-
# config/
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
+
# config/initializers/shrine.rb (Rails)
|
601
|
+
require "image_processing/mini_magick"
|
602
|
+
|
603
|
+
Shrine.plugin :derivation_endpoint,
|
604
|
+
secret_key: "<YOUR SECRET KEY>",
|
605
|
+
prefix: "derivations" # needs to match the mount point in routes
|
606
|
+
|
607
|
+
Shrine.derivation :thumbnail do |file, width, height|
|
608
|
+
ImageProcessing::MiniMagick
|
609
|
+
.source(file)
|
610
|
+
.resize_to_limit!(width.to_i, height.to_i)
|
600
611
|
end
|
601
612
|
```
|
602
613
|
```rb
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
secret_key: "<YOUR SECRET KEY>",
|
608
|
-
prefix: "derivations/image" # needs to match the mount point in routes
|
609
|
-
|
610
|
-
derivation :thumbnail do |file, width, height|
|
611
|
-
ImageProcessing::MiniMagick
|
612
|
-
.source(file)
|
613
|
-
.resize_to_limit!(width.to_i, height.to_i)
|
614
|
-
end
|
614
|
+
# config/routes.rb (Rails)
|
615
|
+
Rails.application.routes.draw do
|
616
|
+
# ...
|
617
|
+
mount Shrine.derivation_endpoint => "/derivations"
|
615
618
|
end
|
616
619
|
```
|
617
620
|
|
@@ -620,7 +623,7 @@ processing:
|
|
620
623
|
|
621
624
|
```rb
|
622
625
|
photo.image.derivation_url(:thumbnail, 600, 400)
|
623
|
-
#=> "/derivations/
|
626
|
+
#=> "/derivations/thumbnail/600/400/eyJpZCI6ImZvbyIsInN0b3JhZ2UiOiJzdG9yZSJ9?signature=..."
|
624
627
|
```
|
625
628
|
|
626
629
|
The on-the-fly processing feature is highly customizable, see the
|
@@ -675,7 +678,7 @@ class ImageUploader < Shrine
|
|
675
678
|
end
|
676
679
|
end
|
677
680
|
```
|
678
|
-
```
|
681
|
+
```
|
679
682
|
uploads/
|
680
683
|
photos/
|
681
684
|
originals/
|
@@ -906,7 +909,7 @@ uploaded_file.exists?
|
|
906
909
|
uploaded_file.download
|
907
910
|
uploaded_file.delete
|
908
911
|
```
|
909
|
-
```
|
912
|
+
```
|
910
913
|
Metadata (32ms) – {:storage=>:store, :io=>StringIO, :uploader=>Shrine}
|
911
914
|
Upload (1523ms) – {:storage=>:store, :location=>"ed0e30ddec8b97813f2c1f4cfd1700b4", :io=>StringIO, :upload_options=>{}, :uploader=>Shrine}
|
912
915
|
Exists (755ms) – {:storage=>:store, :location=>"ed0e30ddec8b97813f2c1f4cfd1700b4", :uploader=>Shrine}
|
@@ -957,7 +960,7 @@ Shrine.logger.level = Logger::WARN
|
|
957
960
|
[`Shrine::UploadedFile`]: https://shrinerb.com/rdoc/classes/Shrine/UploadedFile/InstanceMethods.html
|
958
961
|
|
959
962
|
[attacher]: #attacher
|
960
|
-
[attachment]: #
|
963
|
+
[attachment]: #attaching
|
961
964
|
[backgrounding]: #backgrounding
|
962
965
|
[direct uploads]: #direct-uploads
|
963
966
|
[io abstraction]: #io-abstraction
|
@@ -1001,10 +1004,12 @@ Shrine.logger.level = Logger::WARN
|
|
1001
1004
|
[ImageProcessing::MiniMagick]: https://github.com/janko/image_processing/blob/master/doc/minimagick.md#readme
|
1002
1005
|
[ImageProcessing::Vips]: https://github.com/janko/image_processing/blob/master/doc/vips.md#readme
|
1003
1006
|
[`file`]: http://linux.die.net/man/1/file
|
1007
|
+
[Down]: https://github.com/janko/down
|
1004
1008
|
|
1005
1009
|
[activerecord plugin]: https://shrinerb.com/docs/plugins/activerecord
|
1006
1010
|
[add_metadata plugin]: https://shrinerb.com/docs/plugins/add_metadata
|
1007
1011
|
[backgrounding plugin]: https://shrinerb.com/docs/plugins/backgrounding
|
1012
|
+
[data_uri plugin]: https://shrinerb.com/docs/plugins/data_uri
|
1008
1013
|
[derivation_endpoint plugin]: https://shrinerb.com/docs/plugins/derivation_endpoint
|
1009
1014
|
[derivatives plugin]: https://shrinerb.com/docs/plugins/derivatives
|
1010
1015
|
[determine_mime_type plugin]: https://shrinerb.com/docs/plugins/determine_mime_type
|