shrine 3.2.0 → 3.2.1

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.

Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/doc/attacher.md +2 -2
  4. data/doc/external/articles.md +56 -43
  5. data/doc/getting_started.md +9 -1
  6. data/doc/plugins/column.md +36 -7
  7. data/doc/plugins/default_url.md +3 -3
  8. data/doc/plugins/derivatives.md +10 -10
  9. data/doc/plugins/form_assign.md +5 -5
  10. data/doc/plugins/remote_url.md +6 -1
  11. data/doc/plugins/upload_endpoint.md +1 -1
  12. data/doc/plugins/upload_options.md +1 -1
  13. data/doc/plugins/validation.md +9 -0
  14. data/doc/plugins/versions.md +7 -7
  15. data/doc/processing.md +2 -3
  16. data/doc/release_notes/3.0.0.md +1 -1
  17. data/doc/release_notes/3.2.1.md +32 -0
  18. data/doc/securing_uploads.md +1 -1
  19. data/doc/storage/s3.md +9 -7
  20. data/lib/shrine.rb +4 -4
  21. data/lib/shrine/attachment.rb +2 -2
  22. data/lib/shrine/plugins.rb +22 -0
  23. data/lib/shrine/plugins/add_metadata.rb +1 -1
  24. data/lib/shrine/plugins/default_url.rb +1 -1
  25. data/lib/shrine/plugins/derivation_endpoint.rb +10 -6
  26. data/lib/shrine/plugins/derivatives.rb +4 -4
  27. data/lib/shrine/plugins/entity.rb +6 -6
  28. data/lib/shrine/plugins/model.rb +2 -2
  29. data/lib/shrine/plugins/presign_endpoint.rb +2 -2
  30. data/lib/shrine/plugins/pretty_location.rb +1 -1
  31. data/lib/shrine/plugins/processing.rb +1 -1
  32. data/lib/shrine/plugins/remote_url.rb +3 -3
  33. data/lib/shrine/plugins/upload_endpoint.rb +3 -3
  34. data/lib/shrine/plugins/upload_options.rb +2 -2
  35. data/lib/shrine/plugins/url_options.rb +2 -2
  36. data/lib/shrine/plugins/validation.rb +1 -1
  37. data/lib/shrine/storage/linter.rb +4 -4
  38. data/lib/shrine/storage/s3.rb +6 -2
  39. data/lib/shrine/version.rb +1 -1
  40. data/shrine.gemspec +6 -7
  41. metadata +16 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1879257b21d6aafee3739bb22a37c46abfb7703dde20120445134b4f0ca56a4d
4
- data.tar.gz: c0351dafde054c2bb126b5e16c632cf4ee34ab61c9a301d68564fe75ab1f3d5f
3
+ metadata.gz: c9762e59a3b310aecf9e4c2789e35df5b814826cf1db60e258faed44fdb1efe6
4
+ data.tar.gz: 857d1abbb026440d32e105cbbd248a89792e4f7b094b7e9509c2a735de32dfe0
5
5
  SHA512:
6
- metadata.gz: 95f3ebbf6f08f799d385486464129cfd7228f04d957709593350671d066888bde0dbdc988aca6f843e0b0eb6f13e6938f81a032a272e999903de8fee5d588ca6
7
- data.tar.gz: 4c8f7a1f64e914db4776fab9df2e9753456a095c993a626f45a1c1e1bc189eeb77f3c04187d4bd132f31a2edd163eea2fee21b360cf35a8f6991b970671d615e
6
+ metadata.gz: b295b7d382c7e73384fcb69f3df1b049427ea2c40e5a84bd4505295cdc8e423aee7e8d76d7b153ecf7c5e0dbea6208d1a693448ee6e97037a9ebeff5fb9ebf46
7
+ data.tar.gz: 8263b3c88336b7ab9e7744ab3de1cae8cc00474af72e95d7c85fca96f89f900c6f347dc7ceaf440143ee5410bd7d00a8a85dab342644fb052ccdf81b974a185e
@@ -1,3 +1,11 @@
1
+ ## 3.2.1 (2020-01-12)
2
+
3
+ * `derivation_endpoint` – Use `Rack::Files` constant on Rack >= 2.1 (@janko)
4
+
5
+ * Fix Ruby 2.7 warnings regarding separation of positional and keyword arguments (@janko)
6
+
7
+ * `s3` – Make `S3#open` handle empty S3 objects (@janko)
8
+
1
9
  ## 3.2.0 (2019-12-17) [[release notes]](https://shrinerb.com/docs/release_notes/3.2.0)
2
10
 
3
11
  * `validation` – Run validation on `Attacher#attach` & `Attacher#attach_cached` instead of `Attacher#change` (@janko)
@@ -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)
@@ -4,49 +4,62 @@ title: Articles
4
4
 
5
5
  ## Official articles
6
6
 
7
- * [Introducing Shrine](http://twin.github.io/introducing-shrine)
8
- * [Asynchronous File Uploads](http://twin.github.io/file-uploads-asynchronous-world)
9
- * [Shrine 2.0 Released](https://twin.github.io/shrine-2-0-released/)
10
- * [Shrine meets Transloadit](https://twin.github.io/shrine-meets-transloadit/)
11
- * [Resumable File Uploads in Ruby](https://twin.github.io/resumable-file-uploads-in-ruby/)
12
- * [Adding Direct S3 Uploads to a Roda App with Shrine](https://github.com/shrinerb/shrine/wiki/Adding-Direct-S3-Uploads)
13
- * [Adding Resumable Uploads to a Roda App with Shrine](https://github.com/shrinerb/shrine/wiki/Adding-Resumable-Uploads)
14
- * [Better File Uploads with Shrine: Motivation](https://twin.github.io/better-file-uploads-with-shrine-motivation/)
15
- * [Better File Uploads with Shrine: Uploader](https://twin.github.io/better-file-uploads-with-shrine-uploader/)
16
- * [Better File Uploads with Shrine: Attachment](https://twin.github.io/better-file-uploads-with-shrine-attachment/)
17
- * [Better File Uploads with Shrine: Processing](https://twin.github.io/better-file-uploads-with-shrine-processing/)
18
- * [Better File Uploads with Shrine: Metadata](https://twin.github.io/better-file-uploads-with-shrine-metadata/)
19
- * [Better File Uploads with Shrine: Direct Uploads](https://twin.github.io/better-file-uploads-with-shrine-direct-uploads)
20
- * [Upcoming Features in Shrine 3.0](https://twin.github.io/upcoming-features-in-shrine-3-0/)
21
- * [Shrine 3.0 Released](https://twin.github.io/shrine-3-0-released/)
7
+ | Article | Published |
8
+ | :------- | --------: |
9
+ | [Better File Uploads with Shrine: Eager Processing](https://twin.github.io/better-file-uploads-with-shrine-eager-processing) | 12 Dec 2019 |
10
+ | [Shrine 3.0 Released](https://twin.github.io/shrine-3-0-released/) | 14 Oct 2019 |
11
+ | [Upcoming Features in Shrine 3.0](https://twin.github.io/upcoming-features-in-shrine-3-0/) | 29 Aug 2019 |
12
+ | [Better File Uploads with Shrine: Direct Uploads](https://twin.github.io/better-file-uploads-with-shrine-direct-uploads/) | 08 Jan 2018 |
13
+ | [Better File Uploads with Shrine: Metadata](https://twin.github.io/better-file-uploads-with-shrine-metadata/) | 07 Nov 2016 |
14
+ | [Better File Uploads with Shrine: Processing](https://twin.github.io/better-file-uploads-with-shrine-processing/) | 31 Oct 2016 |
15
+ | [Better File Uploads with Shrine: Attachment](https://twin.github.io/better-file-uploads-with-shrine-attachment/) | 17 Sep 2016 |
16
+ | [Better File Uploads with Shrine: Uploader](https://twin.github.io/better-file-uploads-with-shrine-uploader/) | 16 Sep 2016 |
17
+ | [Better File Uploads with Shrine: Motivation](https://twin.github.io/better-file-uploads-with-shrine-motivation/) | 11 Sep 2016 |
18
+ | [Resumable File Uploads in Ruby](https://twin.github.io/resumable-file-uploads-in-ruby/) | 04 Sep 2016 |
19
+ | [Shrine meets Transloadit](https://twin.github.io/shrine-meets-transloadit/) | 11 Jul 2016 |
20
+ | [Shrine 2.0 Released](https://twin.github.io/shrine-2-0-released/) | 20 May 2016 |
21
+ | [Asynchronous File Uploads](http://twin.github.io/file-uploads-asynchronous-world) | 18 Jan 2016 |
22
+ | [Introducing Shrine](http://twin.github.io/introducing-shrine) | 04 Oct 2015 |
22
23
 
23
24
  ## Other Articles
24
25
 
25
- * [Uploading files with Shrine in Hanami](http://katafrakt.me/2016/02/04/shrine-hanami-uploads/)
26
- * [Rails File Uploading You Can Believe in with Shrine](http://www.sitepoint.com/rails-file-uploading-you-can-believe-in-with-shrine/)
27
- * [Uploading Files With Rails and Shrine](https://code.tutsplus.com/tutorials/uploading-files-with-rails-and-shrine--cms-27596)
28
- * [Upload images using Shrine.rb and Dropzone.js](https://codyeatworld.com/2017/04/18/rails-uploading-images-confidently-with-shrine-rb/)
29
- * [Background file uploads to S3 using Shrine](http://elixirator.com/blog/2017/background-file-uploads-to-s3-using-shrine.html)
30
- * [Rails + Shrine + DropzoneJS](https://stephencodes.com/rails-5-shrine-dropzonejs/)
31
- * [Uploading Files with Rails and ActionCable](https://scotch.io/tutorials/uploading-files-with-rails-and-actioncable)
32
- * [Creating Streaming Radio With Rails and Icecast](https://scotch.io/tutorials/creating-online-streaming-radio-with-rails-and-icecast)
33
- * [Multiple Photo Upload using Shrine](https://github.com/pyksoft/multi-photo-upload#multiple-photo-upload-using-shrine)
34
- * [Store Your Files on S3: Setup & Configuration](https://www.ironin.it/blog/store-your-files-on-s3-using-the-ruby-shrine-gem-part-1.html)
35
- * [Store Your Files on S3: Direct Uploads](https://www.ironin.it/blog/store-your-files-on-s3-using-the-ruby-shrine-gem-part-2.html)
36
- * [Store Your Files on S3: Uploading from a URL](https://www.ironin.it/blog/store-your-files-on-s3-using-the-ruby-shrine-gem-part-3.html)
37
- * [How to use Trix and Shrine for WYSIWYG Editing with Drag-and-Drop Image Uploading](http://headway.io/blog/how-to-use-trix-and-shrine-for-wysiwyg-editing-with-drag-and-drop-image-uploading/)
38
- * [Happy users uploading files with Rails 5, Shrine, and Vue.js](https://itnext.io/happy-users-uploading-files-with-rails-5-shrine-and-vue-js-bbcc470a327f)
39
- * [Notes on study of shrine implementation](https://bibwild.wordpress.com/2018/09/12/notes-on-study-of-shrine-implementation/)
40
- * [GraphQL file upload with Shrine](https://blog.stanko.io/graphql-file-upload-with-shrine-45fa26463c68)
41
-
42
- ## Videos
43
-
44
- * [wroc_love.rb Handling file uploads for a modern developer](https://www.youtube.com/watch?v=fP2JGjTZU2s)
45
- * [File Uploads in Rails with Shrine (GoRails)](https://gorails.com/episodes/file-uploading-with-shrine?autoplay=1)
46
- * [Direct File Uploads to S3: Part 1 (GoRails)](https://gorails.com/episodes/direct-file-uploads-to-s3-part-1?autoplay=1)
47
- * [Direct File Uploads to S3: Part 2 (GoRails)](https://gorails.com/episodes/direct-file-uploads-to-s3-part-2?autoplay=1)
48
- * [Direct File Uploads to S3: Part 3 (GoRails)](https://gorails.com/episodes/direct-file-uploads-to-s3-part-3?autoplay=1)
49
- * [Backgrounding and Video Transcoding (GoRails)](https://gorails.com/episodes/shrine-background-and-video-transcoding?autoplay=1)
50
- * [Multiple File Uploads with Shrine (GoRails)](https://gorails.com/episodes/multiple-file-uploads-with-shrine?autoplay=1)
51
- * [Trix WYSIWYG Editor And File Uploads (GoRails)](https://gorails.com/episodes/trix-editor?autoplay=1)
52
- * [Uploading Files to DigitalOcean Spaces (GoRails)](https://gorails.com/episodes/digital-ocean-spaces-with-rails?autoplay=1)
26
+ | Article | Published |
27
+ | :------ | --------: |
28
+ | [Microsoft Azure data storage library](https://syndicode.com/2019/12/17/microsoft-azure-data-storage-library-rewrite-the-existing-library-to-get-things-done/) | 17 Dec 2019 |
29
+ | [How to use REST clients / native apps to make Shrine client uploads and S3 work for you (no Javascript, just backend)](https://dev.to/rob117/how-to-use-rest-clients--native-apps-to-make-shrine-client-uploads-and-s3-work-for-you-no-javascript-just-backend-322h) | 16 Feb 2019 |
30
+ | [GraphQL file upload with Shrine](https://blog.stanko.io/graphql-file-upload-with-shrine-45fa26463c68) | 02 Jan 2019 |
31
+ | [Notes on study of shrine implementation](https://bibwild.wordpress.com/2018/09/12/notes-on-study-of-shrine-implementation/) | 12 Sep 2018 |
32
+ | [Happy users uploading files with Rails 5, Shrine, and Vue.js](https://itnext.io/happy-users-uploading-files-with-rails-5-shrine-and-vue-js-bbcc470a327f) | 04 Sep 2018 |
33
+ | [Rails 5 + Shrine + DropzoneJS](https://stephencodes.com/rails-5-shrine-dropzonejs/) | 20 Oct 2018 |
34
+ | [How to use Trix and Shrine for WYSIWYG Editing with Drag-and-Drop Image Uploading](http://headway.io/blog/how-to-use-trix-and-shrine-for-wysiwyg-editing-with-drag-and-drop-image-uploading/) | 26 Jan 2018 |
35
+ | [Store Your Files on S3: Uploading from a URL](https://www.ironin.it/blog/store-your-files-on-s3-using-the-ruby-shrine-gem-part-3.html) | 28 Dec 2017 |
36
+ | [Store Your Files on S3: Direct Uploads](https://www.ironin.it/blog/store-your-files-on-s3-using-the-ruby-shrine-gem-part-2.html) | 15 Dec 2017 |
37
+ | [Store Your Files on S3: Setup & Configuration](https://www.ironin.it/blog/store-your-files-on-s3-using-the-ruby-shrine-gem-part-1.html) | 27 Nov 2017 |
38
+ | [Creating Streaming Radio With Rails and Icecast](https://scotch.io/tutorials/creating-online-streaming-radio-with-rails-and-icecast) | 06 Nov 2017 |
39
+ | [Multiple Photo Upload using Shrine](https://github.com/pyksoft/multi-photo-upload#multiple-photo-upload-using-shrine) | 02 Nov 2017 |
40
+ | [Uploading Files with Rails and ActionCable](https://scotch.io/tutorials/uploading-files-with-rails-and-actioncable) | 19 Oct 2017 |
41
+ | [Background file uploads to S3 using Shrine](https://elixirator.com/blog/background-file-uploads-to-s3-using-shrine/) | 21 Jul 2017 |
42
+ | [Upload images using Shrine.rb and Dropzone.js](https://codyeatworld.com/2017/04/18/rails-uploading-images-confidently-with-shrine-rb/) | 18 Apr 2017 |
43
+ | [Uploading Files With Rails and Shrine](https://code.tutsplus.com/tutorials/uploading-files-with-rails-and-shrine--cms-27596) | 26 Dec 2016 |
44
+ | [Rails File Uploading You Can Believe in with Shrine](http://www.sitepoint.com/rails-file-uploading-you-can-believe-in-with-shrine/) | 11 Apr 2016 |
45
+ | [Uploading files with Shrine in Hanami](http://katafrakt.me/2016/02/04/shrine-hanami-uploads/) | 04 Feb 2016 |
46
+
47
+ ## Screencasts
48
+
49
+ | Screencast | Source | Published |
50
+ | :---- | :------ | --------: |
51
+ | [Uploading Files to DigitalOcean Spaces](https://gorails.com/episodes/digital-ocean-spaces-with-rails?autoplay=1) | GoRails | 31 Oct 2017 |
52
+ | [Trix WYSIWYG Editor And File Uploads](https://gorails.com/episodes/trix-editor?autoplay=1) | GoRails | 03 Oct 2017 |
53
+ | [Multiple File Uploads with Shrine](https://gorails.com/episodes/multiple-file-uploads-with-shrine?autoplay=1) | GoRails | 14 Dec 2016 |
54
+ | [Backgrounding and Video Transcoding](https://gorails.com/episodes/shrine-background-and-video-transcoding?autoplay=1) | GoRails | 03 Nov 2016 |
55
+ | [Direct File Uploads to S3: Part 3](https://gorails.com/episodes/direct-file-uploads-to-s3-part-3?autoplay=1) | GoRails | 05 Oct 2016 |
56
+ | [Direct File Uploads to S3: Part 2](https://gorails.com/episodes/direct-file-uploads-to-s3-part-2?autoplay=1) | GoRails | 05 Oct 2016 |
57
+ | [Direct File Uploads to S3: Part 1](https://gorails.com/episodes/direct-file-uploads-to-s3-part-1?autoplay=1) | GoRails | 05 Oct 2016 |
58
+ | [File Uploads in Rails with Shrine](https://gorails.com/episodes/file-uploading-with-shrine?autoplay=1) | GoRails | 23 Sep 2016 |
59
+
60
+ ## Talks
61
+
62
+ | Talk | Source | Date |
63
+ | :---- | :------ | --------: |
64
+ | [Handling file uploads for a modern developer](https://www.youtube.com/watch?v=fP2JGjTZU2s) | wroc_love.rb | 24 Mar 2019 |
65
+ | [Shrine – Handle File Uploads like it's 2017](https://www.youtube.com/watch?v=plD-RkKEay0) | Melbourne Ruby | 27 Feb 2017 |
@@ -110,6 +110,14 @@ form @photo, action: "/photos", enctype: "multipart/form-data" do |f|
110
110
  f.button "Create"
111
111
  end
112
112
  ```
113
+ <!--HTML-->
114
+ ```erb
115
+ <form action="/photos" method="post" enctype="multipart/form-data">
116
+ <input name="photo[image]" type="hidden" value="<%= @photo.cached_image_data %>" />
117
+ <input name="photo[image] "type="file" />
118
+ <input type="submit" value="Create" />
119
+ </form>
120
+ ```
113
121
  <!--END_DOCUSAURUS_CODE_TABS-->
114
122
 
115
123
  Note that the file field needs to go *after* the hidden field, so that
@@ -536,7 +544,7 @@ $ brew install imagemagick vips
536
544
 
537
545
  ### Eager processing
538
546
 
539
- We can can use the [`derivatives`][derivatives plugin] plugin to generate a
547
+ We can use the [`derivatives`][derivatives plugin] plugin to generate a
540
548
  pre-defined set of processed files (e.g. image thumbnails). We do this by
541
549
  registering a derivatives processor block and then explicitly triggering
542
550
  creation:
@@ -66,23 +66,48 @@ If you want to load attachment from a Hash, use `Attacher.from_data` or
66
66
 
67
67
  ## Serializer
68
68
 
69
- By default the `JSON` standard library is used as the serializer, but you can
70
- use your own serializer. The serializer object needs to implement `#dump` and
71
- `#load` methods.
69
+ By default, the `JSON` standard library is used for serializing hash data. With
70
+ the [`model`][model] and [`entity`][entity] plugin, the data is serialized
71
+ before writing to and deserialized after reading from the data attribute.
72
+
73
+ You can also use your own serializer via the `:serializer` option. The
74
+ serializer object needs to implement `#dump` and `#load` methods:
75
+
76
+ ```rb
77
+ class MyDataSerializer
78
+ def self.dump(data)
79
+ data #=> { "id" => "...", "storage" => "...", "metadata" => { ... } }
80
+
81
+ JSON.generate(data) # serialize data, e.g. into JSON
82
+ end
83
+
84
+ def self.load(data)
85
+ data #=> '{"id":"...", "storage":"...", "metadata": {...}}'
86
+
87
+ JSON.parse(data) # deserialize data, e.g. from JSON
88
+ end
89
+ end
90
+
91
+ plugin :column, serializer: MyDataSerializer
92
+ ```
93
+
94
+ Some serialization libraries such as [Oj] and [MessagePack] already implement
95
+ this interface, which simplifies the configuration:
72
96
 
73
97
  ```rb
74
- require "oj"
98
+ require "oj" # https://github.com/ohler55/oj
75
99
 
76
- plugin :column, serializer: Oj # use custom serializer
100
+ plugin :column, serializer: Oj
77
101
  ```
78
102
 
79
- If you want to disable serialization, you can set serializer to `nil`.
103
+ If you want to disable serialization and work with hashes directly, you can set
104
+ `:serializer` to `nil`:
80
105
 
81
106
  ```rb
82
107
  plugin :column, serializer: nil # disable serialization
83
108
  ```
84
109
 
85
- You can also change the serializer on the attacher level:
110
+ The serializer can also be changed for a particular attacher instance:
86
111
 
87
112
  ```rb
88
113
  Shrine::Attacher.new(column_serializer: Oj) # use custom serializer
@@ -90,3 +115,7 @@ Shrine::Attacher.new(column_serializer: nil) # disable serialization
90
115
  ```
91
116
 
92
117
  [column]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/column.rb
118
+ [model]: https://shrinerb.com/docs/plugins/model
119
+ [entity]: https://shrinerb.com/docs/plugins/entity
120
+ [Oj]: https://github.com/ohler55/oj
121
+ [MessagePack]: https://github.com/msgpack/msgpack-ruby
@@ -8,7 +8,7 @@ returned when there is no attached file.
8
8
  ```rb
9
9
  plugin :default_url
10
10
 
11
- Attacher.default_url do |options|
11
+ Attacher.default_url do |**options|
12
12
  "/#{name}/missing.jpg"
13
13
  end
14
14
  ```
@@ -28,7 +28,7 @@ Any URL options passed will be available in the default URL block:
28
28
  attacher.url(foo: "bar")
29
29
  ```
30
30
  ```rb
31
- Attacher.default_url do |options|
31
+ Attacher.default_url do |**options|
32
32
  options #=> { foo: "bar" }
33
33
  end
34
34
  ```
@@ -37,7 +37,7 @@ The default URL block is evaluated in the context of an instance of
37
37
  `Shrine::Attacher`.
38
38
 
39
39
  ```rb
40
- Attacher.default_url do |options|
40
+ Attacher.default_url do |**options|
41
41
  self #=> #<Shrine::Attacher>
42
42
 
43
43
  file #=> #<Shrine::UploadedFile>
@@ -422,11 +422,11 @@ If you already have processed files that you want to save, you can do that with
422
422
  `Attacher#add_derivatives`:
423
423
 
424
424
  ```rb
425
- attacher.add_derivatives(
425
+ attacher.add_derivatives({
426
426
  one: file_1,
427
427
  two: file_2,
428
428
  # ...
429
- )
429
+ })
430
430
 
431
431
  attacher.derivatives #=>
432
432
  # {
@@ -440,7 +440,7 @@ New derivatives will be merged with existing ones:
440
440
 
441
441
  ```rb
442
442
  attacher.derivatives #=> { one: #<Shrine::UploadedFile> }
443
- attacher.add_derivatives(two: two_file)
443
+ attacher.add_derivatives({ two: two_file })
444
444
  attacher.derivatives #=> { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> }
445
445
  ```
446
446
 
@@ -448,7 +448,7 @@ The merging is deep, so the following will work as well:
448
448
 
449
449
  ```rb
450
450
  attacher.derivatives #=> { nested: { one: #<Shrine::UploadedFile> } }
451
- attacher.add_derivatives(nested: { two: two_file })
451
+ attacher.add_derivatives({ nested: { two: two_file } })
452
452
  attacher.derivatives #=> { nested: { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> } }
453
453
  ```
454
454
 
@@ -475,11 +475,11 @@ If you want to upload processed files without setting them, you can use
475
475
  `Attacher#upload_derivatives`:
476
476
 
477
477
  ```rb
478
- derivatives = attacher.upload_derivatives(
478
+ derivatives = attacher.upload_derivatives({
479
479
  one: file_1,
480
480
  two: file_2,
481
481
  # ...
482
- )
482
+ })
483
483
 
484
484
  derivatives #=>
485
485
  # {
@@ -555,7 +555,7 @@ If you want to save already uploaded derivatives, you can use
555
555
 
556
556
  ```rb
557
557
  attacher.derivatives #=> { one: #<Shrine::UploadedFile> }
558
- attacher.merge_derivatives attacher.upload_derivatives(two: two_file)
558
+ attacher.merge_derivatives attacher.upload_derivatives({ two: two_file })
559
559
  attacher.derivatives #=> { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> }
560
560
  ```
561
561
 
@@ -563,7 +563,7 @@ This does a deep merge, so the following will work as well:
563
563
 
564
564
  ```rb
565
565
  attacher.derivatives #=> { nested: { one: #<Shrine::UploadedFile> } }
566
- attacher.merge_derivatives attacher.upload_derivatives(nested: { two: two_file })
566
+ attacher.merge_derivatives attacher.upload_derivatives({ nested: { two: two_file } })
567
567
  attacher.derivatives #=> { nested: { one: #<Shrine::UploadedFile>, two: #<Shrine::UploadedFile> } }
568
568
  ```
569
569
 
@@ -576,7 +576,7 @@ If instead of adding you want to *override* existing derivatives, you can use
576
576
 
577
577
  ```rb
578
578
  attacher.derivatives #=> { one: #<Shrine::UploadedFile> }
579
- attacher.set_derivatives attacher.upload_derivatives(two: two_file)
579
+ attacher.set_derivatives attacher.upload_derivatives({ two: two_file })
580
580
  attacher.derivatives #=> { two: #<Shrine::UploadedFile> }
581
581
  ```
582
582
 
@@ -684,7 +684,7 @@ You can store derivatives even if there is no main attached file:
684
684
 
685
685
  ```rb
686
686
  attacher.file #=> nil
687
- attacher.add_derivatives(one: one_file, two: two_file)
687
+ attacher.add_derivatives({ one: one_file, two: two_file })
688
688
  attacher.data #=>
689
689
  # {
690
690
  # "derivatives" => {
@@ -14,7 +14,7 @@ the attacher:
14
14
 
15
15
  ```rb
16
16
  attacher = photo.image_attacher
17
- attacher.form_assign("image" => file, "title" => "...", "description" => "...")
17
+ attacher.form_assign({ "image" => file, "title" => "...", "description" => "..." })
18
18
  attacher.file #=> #<Shrine::UploadedFile>
19
19
  ```
20
20
 
@@ -22,17 +22,17 @@ It works with `remote_url`, `data_uri`, and `remove_attachment` plugins:
22
22
 
23
23
  ```rb
24
24
  # remote_url plugin
25
- attacher.form_assign("image_remote_url" => "https://example.com/...")
25
+ attacher.form_assign({ "image_remote_url" => "https://example.com/..." })
26
26
  attacher.file #=> #<Shrine::UploadedFile>
27
27
  ```
28
28
  ```rb
29
29
  # data_uri plugin
30
- attacher.form_assign("image_data_uri" => "data:image/jpeg;base64,...")
30
+ attacher.form_assign({ "image_data_uri" => "data:image/jpeg;base64,..." })
31
31
  attacher.file #=> #<Shrine::UploadedFile>
32
32
  ```
33
33
  ```rb
34
34
  # remove_attachment plugin
35
- attacher.form_assign("remove_image" => "1")
35
+ attacher.form_assign({ "remove_image" => "1" })
36
36
  attacher.file #=> nil
37
37
  ```
38
38
 
@@ -40,7 +40,7 @@ The return value is a hash with form params, with file param replaced with
40
40
  cached file data, which can later be assigned again to the record.
41
41
 
42
42
  ```rb
43
- attacher.form_assign("image" => file, "title" => "...", "description" => "...")
43
+ attacher.form_assign({ "image" => file, "title" => "...", "description" => "..." })
44
44
  #=> { :image => '{"id":"...","storage":"...","metadata":"..."}', "title" => "...", "description" => "..." }
45
45
  ```
46
46
 
@@ -40,7 +40,12 @@ around [open-uri].
40
40
  You can pass options to the downloader via the `:downloader` option:
41
41
 
42
42
  ```rb
43
- attacher.assign_remote_url(url, downloader: { 'Authorization' => 'Basic ...' })
43
+ attacher.assign_remote_url url, downloader: {
44
+ headers: { "Authorization" => "Basic ..." },
45
+ read_timeout: 30, open_timeout: 30,
46
+ max_redirects: 5,
47
+ # ...
48
+ }
44
49
  ```
45
50
 
46
51
  You can also change the downloader:
@@ -113,7 +113,7 @@ upload happens independently of a database record.
113
113
  You can also customize the upload itself via the `:upload` option:
114
114
 
115
115
  ```rb
116
- plugin :upload_endpoint, upload: -> (io, **options, request) do
116
+ plugin :upload_endpoint, upload: -> (io, options, request) do
117
117
  Shrine.upload(io, :cache, **options)
118
118
  end
119
119
  ```
@@ -13,7 +13,7 @@ Keys are names of the registered storages, and values are either hashes or
13
13
  blocks.
14
14
 
15
15
  ```rb
16
- plugin :upload_options, store: -> (io, **options) do
16
+ plugin :upload_options, store: -> (io, options) do
17
17
  if options[:derivative]
18
18
  { acl: "public-read" }
19
19
  else
@@ -84,5 +84,14 @@ You can also skip validation by passing `validate: false`:
84
84
  attacher.assign(file, validate: false) # skips validation
85
85
  ```
86
86
 
87
+ ## Manual validation
88
+
89
+ You can also run validation manually via `Attacher#validate`:
90
+
91
+ ```rb
92
+ attacher.set(uploaded_file) # doesn't trigger validation
93
+ attacher.validate # runs validation
94
+ ```
95
+
87
96
  [validation]: https://github.com/shrinerb/shrine/blob/master/lib/shrine/plugins/validation.rb
88
97
  [validation_helpers]: https://shrinerb.com/docs/plugins/validation_helpers
@@ -17,7 +17,7 @@ require "image_processing/mini_magick"
17
17
 
18
18
  plugin :processing
19
19
 
20
- process(:store) do |io, context|
20
+ process(:store) do |io, **options|
21
21
  versions = { original: io } # retain original
22
22
 
23
23
  io.download do |original|
@@ -120,7 +120,7 @@ In addition to Hashes, the plugin also supports Arrays of files. For example,
120
120
  you might want to split a PDf into pages:
121
121
 
122
122
  ```rb
123
- process(:store) do |io, context|
123
+ process(:store) do |io, **options|
124
124
  versions = { pages: [] }
125
125
 
126
126
  io.download do |pdf|
@@ -146,7 +146,7 @@ which you can do by adding the yielded `Shrine::UploadedFile` object as one of
146
146
  the versions, by convention named `:original`:
147
147
 
148
148
  ```rb
149
- process(:store) do |io, context|
149
+ process(:store) do |io, **options|
150
150
  # processing thumbnail
151
151
  { original: io, thumbnail: thumbnail }
152
152
  end
@@ -163,12 +163,12 @@ The version name will be available via `:version` when generating location or a
163
163
  default URL.
164
164
 
165
165
  ```rb
166
- def generate_location(io, context)
167
- "uploads/#{context[:version]}-#{super}"
166
+ def generate_location(io, version: nil, **)
167
+ "uploads/#{version}-#{super}"
168
168
  end
169
169
 
170
- Attacher.default_url do |options|
171
- "/images/defaults/#{options[:version]}.jpg"
170
+ Attacher.default_url do |version: nil, **|
171
+ "/images/defaults/#{version}.jpg"
172
172
  end
173
173
  ```
174
174
 
@@ -114,9 +114,8 @@ Attacher.derivatives do |original|
114
114
  end
115
115
  ```
116
116
 
117
- If you find yourself branching a lot based on MIME type, the
118
- [`type_predicates`][type_predicates] plugin provides convenient predicate
119
- methods for that.
117
+ The [`type_predicates`][type_predicates] plugin provides convenient predicate
118
+ methods for branching based on the file type.
120
119
 
121
120
  ### Backgrounding
122
121
 
@@ -366,7 +366,7 @@ end
366
366
  ```
367
367
  ```rb
368
368
  attacher = photo.image_attacher
369
- attacher.form_assign("image" => file, "title" => "...", "description" => "...")
369
+ attacher.form_assign({ "image" => file, "title" => "...", "description" => "..." })
370
370
  attacher.file #=> #<Shrine::UploadedFile id="..." storage=:cache ...>
371
371
  ```
372
372
 
@@ -0,0 +1,32 @@
1
+ ---
2
+ title: Shrine 3.2.1
3
+ ---
4
+
5
+ ## Ruby 2.7 compatibility
6
+
7
+ * Shrine doesn't trigger [Ruby 2.7 warnings for separation of positional and
8
+ keyword arguments][kwargs] anymore.
9
+
10
+ * Down 5.1.0 has been released, which resolves warnings and a `FrozenError`
11
+ exception on Ruby 2.7. Shrine now requires at least this version of Down.
12
+
13
+ If you're using `Down::Http`, make sure you're using http.rb 4.3.0 or newer.
14
+
15
+ * ImageProcessing 1.10.3 gem has been released which resolves Ruby 2.7 warnings
16
+ as well. If you're using it for image processing, make sure to upgrade to
17
+ this version:
18
+
19
+ ```rb
20
+ gem "image_processing", ">= 1.10.3", "< 2"
21
+ ```
22
+
23
+ ## Rack 2.1.0 compatibility
24
+
25
+ * The `derivation_endpoint` plugin now uses `Rack::Files` on Rack 2.1.0 or
26
+ newer.
27
+
28
+ ## Other improvements
29
+
30
+ * The `S3#open` method now handles empty S3 objects.
31
+
32
+ [kwargs]: https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/
@@ -63,7 +63,7 @@ in the `:max_size` option to reject files that are larger than the specified
63
63
  limit:
64
64
 
65
65
  ```rb
66
- plugin :upload_endpoint, max_size: 100*1024*1024 # 20 MB
66
+ plugin :upload_endpoint, max_size: 100*1024*1024 # 100 MB
67
67
  ```
68
68
 
69
69
  If you're doing direct uploads to Amazon S3 using the `presign_endpoint`
@@ -27,13 +27,15 @@ s3 = Shrine::Storage::S3.new(
27
27
  )
28
28
  ```
29
29
 
30
- The `:access_key_id` and `:secret_access_key` options are just one form of
31
- authentication, see [`Aws::S3::Client#initialize`] docs for more details.
30
+ > The storage requires the following AWS S3 permissions:
31
+ >
32
+ > * `s3:ListBucket` for the bucket resource
33
+ > * `s3:GetObject`, `s3:PutObject`, `s3:PutObjectAcl`, `s3:DeleteObject`,
34
+ > `s3:ListMultipartUploadParts` and `s3:AbortMultipartUpload` for the object
35
+ > resources
32
36
 
33
- > The core features of this storage require the following AWS permissions:
34
- `s3:ListBucket`, `s3:PutObject`, `s3:GetObject`, and `s3:DeleteObject`. If you
35
- have additional upload options configured such as setting object ACLs, then
36
- additional permissions may be required.
37
+ > The `:access_key_id` and `:secret_access_key` options is just one form of
38
+ > authentication, see the [AWS SDK docs][credentials] for more options.
37
39
 
38
40
  The storage exposes the underlying Aws objects:
39
41
 
@@ -312,7 +314,7 @@ s3.clear! { |object| object.last_modified < Time.now - 7*24*60*60 }
312
314
  [object lifecycle]: http://docs.aws.amazon.com/AmazonS3/latest/UG/lifecycle-configuration-bucket-no-versioning.html
313
315
  [serve private content via CloudFront]: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html
314
316
  [`Aws::CloudFront::UrlSigner`]: https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/CloudFront/UrlSigner.html
315
- [`Aws::S3::Client#initialize`]: https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Client.html#initialize-instance_method
317
+ [credentials]: https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/setup-config.html
316
318
  [`Aws::S3::Object#presigned_post`]: https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#presigned_post-instance_method
317
319
  [`Aws::S3::Object#presigned_url`]: https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#presigned_url-instance_method
318
320
  [#348]: https://github.com/shrinerb/shrine/issues/348
@@ -68,9 +68,9 @@ class Shrine
68
68
  #
69
69
  # Shrine.plugin MyPlugin
70
70
  # Shrine.plugin :my_plugin
71
- def plugin(plugin, *args, &block)
71
+ def plugin(plugin, *args, **kwargs, &block)
72
72
  plugin = Plugins.load_plugin(plugin) if plugin.is_a?(Symbol)
73
- plugin.load_dependencies(self, *args, &block) if plugin.respond_to?(:load_dependencies)
73
+ Plugins.load_dependencies(plugin, self, *args, **kwargs, &block)
74
74
  self.include(plugin::InstanceMethods) if defined?(plugin::InstanceMethods)
75
75
  self.extend(plugin::ClassMethods) if defined?(plugin::ClassMethods)
76
76
  self::UploadedFile.include(plugin::FileMethods) if defined?(plugin::FileMethods)
@@ -79,7 +79,7 @@ class Shrine
79
79
  self::Attachment.extend(plugin::AttachmentClassMethods) if defined?(plugin::AttachmentClassMethods)
80
80
  self::Attacher.include(plugin::AttacherMethods) if defined?(plugin::AttacherMethods)
81
81
  self::Attacher.extend(plugin::AttacherClassMethods) if defined?(plugin::AttacherClassMethods)
82
- plugin.configure(self, *args, &block) if plugin.respond_to?(:configure)
82
+ Plugins.configure(plugin, self, *args, **kwargs, &block)
83
83
  plugin
84
84
  end
85
85
 
@@ -297,7 +297,7 @@ class Shrine
297
297
  # Retrieves the location for the given IO and context. First it looks
298
298
  # for the `:location` option, otherwise it calls #generate_location.
299
299
  def get_location(io, location: nil, **options)
300
- location ||= generate_location(io, options)
300
+ location ||= generate_location(io, **options)
301
301
  location or fail Error, "location generated for #{io.inspect} was nil"
302
302
  end
303
303
 
@@ -22,8 +22,8 @@ class Shrine
22
22
  # Shorthand for `Attachment.new`.
23
23
  #
24
24
  # Shrine::Attachment[:image]
25
- def [](*args)
26
- new(*args)
25
+ def [](*args, **options)
26
+ new(*args, **options)
27
27
  end
28
28
  end
29
29
 
@@ -18,6 +18,28 @@ class Shrine
18
18
  plugin
19
19
  end
20
20
 
21
+ # Delegate call to the plugin in a way that works across Ruby versions.
22
+ def self.load_dependencies(plugin, uploader, *args, **kwargs, &block)
23
+ return unless plugin.respond_to?(:load_dependencies)
24
+
25
+ if kwargs.any?
26
+ plugin.load_dependencies(uploader, *args, **kwargs, &block)
27
+ else
28
+ plugin.load_dependencies(uploader, *args, &block)
29
+ end
30
+ end
31
+
32
+ # Delegate call to the plugin in a way that works across Ruby versions.
33
+ def self.configure(plugin, uploader, *args, **kwargs, &block)
34
+ return unless plugin.respond_to?(:configure)
35
+
36
+ if kwargs.any?
37
+ plugin.configure(uploader, *args, **kwargs, &block)
38
+ else
39
+ plugin.configure(uploader, *args, &block)
40
+ end
41
+ end
42
+
21
43
  # Register the given plugin with Shrine, so that it can be loaded using
22
44
  # `Shrine.plugin` with a symbol. Should be used by plugin files. Example:
23
45
  #
@@ -41,7 +41,7 @@ class Shrine
41
41
 
42
42
  def extract_custom_metadata(io, **options)
43
43
  opts[:add_metadata][:definitions].each do |name, block|
44
- result = instance_exec(io, options, &block)
44
+ result = instance_exec(io, **options, &block)
45
45
 
46
46
  if name
47
47
  options[:metadata].merge! name.to_s => result
@@ -25,7 +25,7 @@ class Shrine
25
25
  def default_url(**options)
26
26
  return unless default_url_block
27
27
 
28
- url = instance_exec(options, &default_url_block)
28
+ url = instance_exec(**options, &default_url_block)
29
29
 
30
30
  [*default_url_host, url].join
31
31
  end
@@ -475,9 +475,9 @@ class Shrine
475
475
  file_response(derivative, env)
476
476
  end
477
477
 
478
- # Generates a Rack response triple from a local file using `Rack::File`.
479
- # Fills in `Content-Type` and `Content-Disposition` response headers from
480
- # derivation options and file extension of the derivation result.
478
+ # Generates a Rack response triple from a local file. Fills in
479
+ # `Content-Type` and `Content-Disposition` response headers from derivation
480
+ # options and file extension of the derivation result.
481
481
  def file_response(file, env)
482
482
  response = rack_file_response(file.path, env)
483
483
 
@@ -511,7 +511,7 @@ class Shrine
511
511
  end
512
512
 
513
513
  if upload_redirect
514
- redirect_url = uploaded_file.url(upload_redirect_url_options)
514
+ redirect_url = uploaded_file.url(**upload_redirect_url_options)
515
515
 
516
516
  [302, { "Location" => redirect_url }, []]
517
517
  else
@@ -528,10 +528,14 @@ class Shrine
528
528
  end
529
529
  end
530
530
 
531
- # We call `Rack::File` with no default `Content-Type`, and make sure we
531
+ # We call `Rack::Files` with no default `Content-Type`, and make sure we
532
532
  # stay compatible with both Rack 2.x and 1.6.x.
533
533
  def rack_file_response(path, env)
534
- server = Rack::File.new("", {}, nil)
534
+ if Rack.release >= "2.1"
535
+ server = Rack::Files.new("", {}, nil)
536
+ else
537
+ server = Rack::File.new("", {}, nil)
538
+ end
535
539
 
536
540
  if Rack.release > "2"
537
541
  server.serving(Rack::Request.new(env), path)
@@ -40,8 +40,8 @@ class Shrine
40
40
  def define_model_methods(name)
41
41
  super if defined?(super)
42
42
 
43
- define_method(:"#{name}_derivatives!") do |*args|
44
- send(:"#{name}_attacher").create_derivatives(*args)
43
+ define_method(:"#{name}_derivatives!") do |*args, **options|
44
+ send(:"#{name}_attacher").create_derivatives(*args, **options)
45
45
  end
46
46
  end
47
47
  end
@@ -462,8 +462,8 @@ class Shrine
462
462
  # Iterates through nested derivatives and maps results.
463
463
  #
464
464
  # attacher.map_derivative(derivatives) { |path, file| ... }
465
- def map_derivative(*args, &block)
466
- shrine_class.map_derivative(*args, &block)
465
+ def map_derivative(derivatives, **options, &block)
466
+ shrine_class.map_derivative(derivatives, **options, &block)
467
467
  end
468
468
 
469
469
  private
@@ -41,27 +41,27 @@ class Shrine
41
41
  end
42
42
 
43
43
  # Returns the URL to the attached file.
44
- define_method :"#{name}_url" do |*args|
45
- send(:"#{name}_attacher").url(*args)
44
+ define_method :"#{name}_url" do |*args, **options|
45
+ send(:"#{name}_attacher").url(*args, **options)
46
46
  end
47
47
 
48
48
  # Returns an attacher instance.
49
49
  define_method :"#{name}_attacher" do |**options|
50
- attachment.send(:attacher, self, options)
50
+ attachment.send(:attacher, self, **options)
51
51
  end
52
52
  end
53
53
 
54
54
  # Returns the class attacher instance with loaded entity. It's not
55
55
  # memoized because the entity object could be frozen.
56
- def attacher(record, options)
57
- attacher = class_attacher(options)
56
+ def attacher(record, **options)
57
+ attacher = class_attacher(**options)
58
58
  attacher.load_entity(record, @name)
59
59
  attacher
60
60
  end
61
61
 
62
62
  # Creates an instance of the corresponding attacher class with set
63
63
  # name.
64
- def class_attacher(options)
64
+ def class_attacher(**options)
65
65
  attacher = shrine_class::Attacher.new(**@options, **options)
66
66
  attacher.instance_variable_set(:@name, @name)
67
67
  attacher
@@ -55,11 +55,11 @@ class Shrine
55
55
  end
56
56
 
57
57
  # Memoizes the attacher instance into an instance variable.
58
- def attacher(record, options)
58
+ def attacher(record, **options)
59
59
  return super unless model?
60
60
 
61
61
  if !record.instance_variable_get(:"@#{@name}_attacher") || options.any?
62
- attacher = class_attacher(options)
62
+ attacher = class_attacher(**options)
63
63
  attacher.load_model(record, @name)
64
64
 
65
65
  record.instance_variable_set(:"@#{@name}_attacher", attacher)
@@ -8,7 +8,7 @@ class Shrine
8
8
  module Plugins
9
9
  # Documentation can be found on https://shrinerb.com/docs/plugins/presign_endpoint
10
10
  module PresignEndpoint
11
- def self.configure(uploader, opts = {})
11
+ def self.configure(uploader, **opts)
12
12
  uploader.opts[:presign_endpoint] ||= {}
13
13
  uploader.opts[:presign_endpoint].merge!(opts)
14
14
  end
@@ -135,7 +135,7 @@ class Shrine
135
135
  if @presign
136
136
  data = @presign.call(location, options, request)
137
137
  else
138
- data = storage.presign(location, options)
138
+ data = storage.presign(location, **options)
139
139
  end
140
140
 
141
141
  { fields: {}, headers: {} }.merge(data.to_h)
@@ -11,7 +11,7 @@ class Shrine
11
11
 
12
12
  module InstanceMethods
13
13
  def generate_location(io, **options)
14
- pretty_location(io, options)
14
+ pretty_location(io, **options)
15
15
  end
16
16
 
17
17
  def pretty_location(io, name: nil, record: nil, version: nil, derivative: nil, identifier: nil, metadata: {}, **)
@@ -33,7 +33,7 @@ class Shrine
33
33
  def process(io, **options)
34
34
  pipeline = processing_pipeline(options[:action])
35
35
  pipeline.inject(io) do |input, processor|
36
- instance_exec(input, options, &processor) || input
36
+ instance_exec(input, **options, &processor) || input
37
37
  end
38
38
  end
39
39
 
@@ -16,7 +16,7 @@ class Shrine
16
16
  }.inspect}"
17
17
  end
18
18
 
19
- DOWNLOADER = -> (url, options) { Down.download(url, options) }
19
+ DOWNLOADER = -> (url, **options) { Down.download(url, **options) }
20
20
 
21
21
  def self.load_dependencies(uploader, *)
22
22
  uploader.plugin :validation
@@ -63,7 +63,7 @@ class Shrine
63
63
  private
64
64
 
65
65
  def download_remote_url(url, options)
66
- opts[:remote_url][:downloader].call(url, options)
66
+ opts[:remote_url][:downloader].call(url, **options)
67
67
  rescue Down::TooLarge
68
68
  fail DownloadError, "remote file too large"
69
69
  rescue Down::Error
@@ -87,7 +87,7 @@ class Shrine
87
87
  def assign_remote_url(url, downloader: {}, **options)
88
88
  return if url == "" || url.nil?
89
89
 
90
- downloaded_file = shrine_class.remote_url(url, downloader)
90
+ downloaded_file = shrine_class.remote_url(url, **downloader)
91
91
  attach_cached(downloaded_file, **options)
92
92
  rescue DownloadError => error
93
93
  errors.clear << remote_url_error_message(url, error)
@@ -9,11 +9,11 @@ class Shrine
9
9
  module Plugins
10
10
  # Documentation can be found on https://shrinerb.com/docs/plugins/upload_endpoint
11
11
  module UploadEndpoint
12
- def self.load_dependencies(uploader, opts = {})
12
+ def self.load_dependencies(uploader, **)
13
13
  uploader.plugin :rack_file
14
14
  end
15
15
 
16
- def self.configure(uploader, opts = {})
16
+ def self.configure(uploader, **opts)
17
17
  uploader.opts[:upload_endpoint] ||= {}
18
18
  uploader.opts[:upload_endpoint].merge!(opts)
19
19
  end
@@ -156,7 +156,7 @@ class Shrine
156
156
  if @upload
157
157
  @upload.call(io, context, request)
158
158
  else
159
- uploader.upload(io, context)
159
+ uploader.upload(io, **context)
160
160
  end
161
161
  end
162
162
 
@@ -4,9 +4,9 @@ class Shrine
4
4
  module Plugins
5
5
  # Documentation can be found on https://shrinerb.com/docs/plugins/upload_options
6
6
  module UploadOptions
7
- def self.configure(uploader, options = {})
7
+ def self.configure(uploader, **opts)
8
8
  uploader.opts[:upload_options] ||= {}
9
- uploader.opts[:upload_options].merge!(options)
9
+ uploader.opts[:upload_options].merge!(opts)
10
10
  end
11
11
 
12
12
  module InstanceMethods
@@ -4,9 +4,9 @@ class Shrine
4
4
  module Plugins
5
5
  # Documentation can be found on https://shrinerb.com/docs/plugins/url_options
6
6
  module UrlOptions
7
- def self.configure(uploader, **options)
7
+ def self.configure(uploader, **opts)
8
8
  uploader.opts[:url_options] ||= {}
9
- uploader.opts[:url_options].merge!(options)
9
+ uploader.opts[:url_options].merge!(opts)
10
10
  end
11
11
 
12
12
  module FileMethods
@@ -54,7 +54,7 @@ class Shrine
54
54
  # Calls validation appropriately based on the :validate value.
55
55
  def validation(argument)
56
56
  case argument
57
- when Hash then validate(argument)
57
+ when Hash then validate(**argument)
58
58
  when false then errors.clear # skip validation
59
59
  else validate
60
60
  end
@@ -35,7 +35,7 @@ class Shrine
35
35
  end
36
36
 
37
37
  def call(io_factory = default_io_factory)
38
- storage.upload(io_factory.call, id = "foo", {})
38
+ storage.upload(io_factory.call, id = "foo", shrine_metadata: { "foo" => "bar" })
39
39
 
40
40
  lint_open(id)
41
41
  lint_exists(id)
@@ -67,13 +67,13 @@ class Shrine
67
67
  end
68
68
 
69
69
  def lint_open(id)
70
- opened = storage.open(id, {})
70
+ opened = storage.open(id)
71
71
  error :open, "doesn't return a valid IO object" if !io?(opened)
72
72
  error :open, "returns an empty IO object" if opened.read.empty?
73
73
  opened.close
74
74
 
75
75
  begin
76
- storage.open(@nonexisting, {})
76
+ storage.open(@nonexisting)
77
77
  error :open, "should raise an exception on nonexisting file"
78
78
  rescue Shrine::FileNotFound
79
79
  rescue => exception
@@ -107,7 +107,7 @@ class Shrine
107
107
  end
108
108
 
109
109
  def lint_presign(id)
110
- data = storage.presign(id, {})
110
+ data = storage.presign(id)
111
111
  error :presign, "result should be a Hash" unless data.respond_to?(:to_h)
112
112
  error :presign, "result should include :method key" unless data.to_h.key?(:method)
113
113
  error :presign, "result should include :url key" unless data.to_h.key?(:url)
@@ -282,10 +282,14 @@ class Shrine
282
282
  # Aws::S3::Object#get doesn't allow us to get the content length of the
283
283
  # object before the content is downloaded, so we hack our way around it.
284
284
  def get_object(object, params)
285
- req = client.build_request(:get_object, **params, bucket: bucket.name, key: object.key)
285
+ req = client.build_request(:get_object, bucket: bucket.name, key: object.key, **params)
286
286
 
287
287
  body = req.enum_for(:send_request)
288
- body.peek # start the request
288
+ begin
289
+ body.peek # start the request
290
+ rescue StopIteration
291
+ # the S3 object is empty
292
+ end
289
293
 
290
294
  content_length = Integer(req.context.http_response.headers["Content-Length"])
291
295
  chunks = Enumerator.new { |y| loop { y << body.next } }
@@ -8,7 +8,7 @@ class Shrine
8
8
  module VERSION
9
9
  MAJOR = 3
10
10
  MINOR = 2
11
- TINY = 0
11
+ TINY = 1
12
12
  PRE = nil
13
13
 
14
14
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
@@ -33,18 +33,17 @@ direct uploads for fully asynchronous user experience.
33
33
  gem.files = Dir["README.md", "LICENSE.txt", "CHANGELOG.md", "lib/**/*.rb", "shrine.gemspec", "doc/**/*.md"]
34
34
  gem.require_path = "lib"
35
35
 
36
- gem.add_dependency "down", "~> 5.0"
36
+ gem.add_dependency "down", "~> 5.1"
37
37
  gem.add_dependency "content_disposition", "~> 1.0"
38
38
 
39
39
  # general testing helpers
40
40
  gem.add_development_dependency "rake", ">= 11.1"
41
41
  gem.add_development_dependency "minitest", "~> 5.8"
42
- gem.add_development_dependency "mocha", "~> 1.4"
43
- gem.add_development_dependency "dry-initializer"
42
+ gem.add_development_dependency "mocha", "~> 1.11"
44
43
 
45
44
  # for endpoint plugins
46
45
  gem.add_development_dependency "rack", "~> 2.0"
47
- gem.add_development_dependency "http-form_data", "~> 2.0"
46
+ gem.add_development_dependency "http-form_data", "~> 2.2"
48
47
  gem.add_development_dependency "rack-test_app"
49
48
 
50
49
  # for determine_mime_type plugin
@@ -67,10 +66,10 @@ direct uploads for fully asynchronous user experience.
67
66
 
68
67
  # for instrumentation plugin
69
68
  gem.add_development_dependency "dry-monitor"
70
- gem.add_development_dependency "activesupport", "~> 5.2.0"
69
+ gem.add_development_dependency "activesupport", RUBY_VERSION >= "2.5" ? "~> 6.0" : "~> 5.2"
71
70
 
72
71
  # for ORM plugins
73
72
  gem.add_development_dependency "sequel"
74
- gem.add_development_dependency "activerecord", "~> 5.2.0"
75
- gem.add_development_dependency "sqlite3", "~> 1.3.6" unless RUBY_ENGINE == "jruby"
73
+ gem.add_development_dependency "activerecord", RUBY_VERSION >= "2.5" ? "~> 6.0" : "~> 5.2"
74
+ gem.add_development_dependency "sqlite3", "~> 1.4" unless RUBY_ENGINE == "jruby"
76
75
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shrine
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.0
4
+ version: 3.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Janko Marohnić
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-17 00:00:00.000000000 Z
11
+ date: 2020-01-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: down
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '5.0'
19
+ version: '5.1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '5.0'
26
+ version: '5.1'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: content_disposition
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -72,28 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '1.4'
75
+ version: '1.11'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '1.4'
83
- - !ruby/object:Gem::Dependency
84
- name: dry-initializer
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
82
+ version: '1.11'
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: rack
99
85
  requirement: !ruby/object:Gem::Requirement
@@ -114,14 +100,14 @@ dependencies:
114
100
  requirements:
115
101
  - - "~>"
116
102
  - !ruby/object:Gem::Version
117
- version: '2.0'
103
+ version: '2.2'
118
104
  type: :development
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
107
  requirements:
122
108
  - - "~>"
123
109
  - !ruby/object:Gem::Version
124
- version: '2.0'
110
+ version: '2.2'
125
111
  - !ruby/object:Gem::Dependency
126
112
  name: rack-test_app
127
113
  requirement: !ruby/object:Gem::Requirement
@@ -296,14 +282,14 @@ dependencies:
296
282
  requirements:
297
283
  - - "~>"
298
284
  - !ruby/object:Gem::Version
299
- version: 5.2.0
285
+ version: '6.0'
300
286
  type: :development
301
287
  prerelease: false
302
288
  version_requirements: !ruby/object:Gem::Requirement
303
289
  requirements:
304
290
  - - "~>"
305
291
  - !ruby/object:Gem::Version
306
- version: 5.2.0
292
+ version: '6.0'
307
293
  - !ruby/object:Gem::Dependency
308
294
  name: sequel
309
295
  requirement: !ruby/object:Gem::Requirement
@@ -324,28 +310,28 @@ dependencies:
324
310
  requirements:
325
311
  - - "~>"
326
312
  - !ruby/object:Gem::Version
327
- version: 5.2.0
313
+ version: '6.0'
328
314
  type: :development
329
315
  prerelease: false
330
316
  version_requirements: !ruby/object:Gem::Requirement
331
317
  requirements:
332
318
  - - "~>"
333
319
  - !ruby/object:Gem::Version
334
- version: 5.2.0
320
+ version: '6.0'
335
321
  - !ruby/object:Gem::Dependency
336
322
  name: sqlite3
337
323
  requirement: !ruby/object:Gem::Requirement
338
324
  requirements:
339
325
  - - "~>"
340
326
  - !ruby/object:Gem::Version
341
- version: 1.3.6
327
+ version: '1.4'
342
328
  type: :development
343
329
  prerelease: false
344
330
  version_requirements: !ruby/object:Gem::Requirement
345
331
  requirements:
346
332
  - - "~>"
347
333
  - !ruby/object:Gem::Version
348
- version: 1.3.6
334
+ version: '1.4'
349
335
  description: |
350
336
  Shrine is a toolkit for file attachments in Ruby applications. It supports
351
337
  uploading, downloading, processing and deleting IO objects, backed by various
@@ -470,6 +456,7 @@ files:
470
456
  - doc/release_notes/3.0.1.md
471
457
  - doc/release_notes/3.1.0.md
472
458
  - doc/release_notes/3.2.0.md
459
+ - doc/release_notes/3.2.1.md
473
460
  - doc/retrieving_uploads.md
474
461
  - doc/securing_uploads.md
475
462
  - doc/storage/file_system.md
@@ -564,7 +551,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
564
551
  - !ruby/object:Gem::Version
565
552
  version: '0'
566
553
  requirements: []
567
- rubygems_version: 3.1.1
554
+ rubygems_version: 3.1.2
568
555
  signing_key:
569
556
  specification_version: 4
570
557
  summary: Toolkit for file attachments in Ruby applications