shrine 3.4.0 → 3.10.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 +96 -0
- data/README.md +11 -11
- data/doc/advantages.md +1 -1
- data/doc/attacher.md +1 -1
- data/doc/carrierwave.md +2 -2
- data/doc/changing_derivatives.md +2 -1
- data/doc/changing_location.md +19 -6
- data/doc/design.md +4 -4
- data/doc/external/articles.md +16 -16
- data/doc/external/extensions.md +1 -1
- data/doc/getting_started.md +73 -30
- data/doc/multiple_files.md +57 -22
- data/doc/plugins/activerecord.md +91 -0
- data/doc/plugins/backgrounding.md +30 -4
- data/doc/plugins/data_uri.md +15 -0
- data/doc/plugins/derivation_endpoint.md +39 -1
- data/doc/plugins/derivatives.md +13 -2
- data/doc/plugins/download_endpoint.md +16 -4
- data/doc/plugins/dynamic_storage.md +15 -0
- data/doc/plugins/fallback_storage.md +90 -0
- data/doc/plugins/keep_files.md +6 -4
- data/doc/plugins/rack_response.md +9 -0
- data/doc/plugins/refresh_metadata.md +20 -0
- data/doc/plugins/sequel.md +57 -0
- data/doc/plugins/signature.md +8 -6
- data/doc/plugins/tempfile.md +14 -6
- data/doc/plugins/upload_options.md +12 -0
- data/doc/plugins/url_options.md +12 -0
- data/doc/plugins/validation_helpers.md +1 -1
- data/doc/processing.md +5 -3
- data/doc/refile.md +3 -3
- data/doc/release_notes/2.1.0.md +1 -1
- data/doc/release_notes/3.10.0.md +30 -0
- data/doc/release_notes/3.5.0.md +63 -0
- data/doc/release_notes/3.6.0.md +23 -0
- data/doc/release_notes/3.7.0.md +75 -0
- data/doc/release_notes/3.7.1.md +31 -0
- data/doc/release_notes/3.8.0.md +37 -0
- data/doc/release_notes/3.9.0.md +42 -0
- data/doc/retrieving_uploads.md +1 -1
- data/doc/storage/s3.md +10 -0
- data/doc/testing.md +45 -17
- data/doc/upgrading_to_3.md +3 -5
- data/lib/shrine/attacher.rb +41 -29
- data/lib/shrine/attachment.rb +2 -2
- data/lib/shrine/plugins/_persistence.rb +1 -1
- data/lib/shrine/plugins/_urlsafe_serialization.rb +4 -4
- data/lib/shrine/plugins/activerecord.rb +25 -4
- data/lib/shrine/plugins/add_metadata.rb +2 -4
- data/lib/shrine/plugins/atomic_helpers.rb +7 -7
- data/lib/shrine/plugins/backgrounding.rb +10 -10
- data/lib/shrine/plugins/column.rb +7 -5
- data/lib/shrine/plugins/data_uri.rb +28 -3
- data/lib/shrine/plugins/default_url.rb +4 -4
- data/lib/shrine/plugins/delete_raw.rb +2 -2
- data/lib/shrine/plugins/derivation_endpoint.rb +65 -59
- data/lib/shrine/plugins/derivatives.rb +35 -21
- data/lib/shrine/plugins/download_endpoint.rb +72 -11
- data/lib/shrine/plugins/entity.rb +15 -9
- data/lib/shrine/plugins/fallback_storage.rb +51 -0
- data/lib/shrine/plugins/infer_extension.rb +5 -1
- data/lib/shrine/plugins/instrumentation.rb +13 -9
- data/lib/shrine/plugins/metadata_attributes.rb +1 -1
- data/lib/shrine/plugins/mirroring.rb +10 -10
- data/lib/shrine/plugins/model.rb +12 -10
- data/lib/shrine/plugins/presign_endpoint.rb +13 -10
- data/lib/shrine/plugins/pretty_location.rb +2 -2
- data/lib/shrine/plugins/processing.rb +3 -3
- data/lib/shrine/plugins/rack_file.rb +2 -2
- data/lib/shrine/plugins/rack_response.rb +12 -6
- data/lib/shrine/plugins/refresh_metadata.rb +6 -6
- data/lib/shrine/plugins/remote_url.rb +4 -4
- data/lib/shrine/plugins/remove_attachment.rb +2 -0
- data/lib/shrine/plugins/remove_invalid.rb +4 -0
- data/lib/shrine/plugins/restore_cached_data.rb +3 -3
- data/lib/shrine/plugins/sequel.rb +15 -1
- data/lib/shrine/plugins/signature.rb +2 -2
- data/lib/shrine/plugins/store_dimensions.rb +2 -2
- data/lib/shrine/plugins/tempfile.rb +0 -2
- data/lib/shrine/plugins/upload_endpoint.rb +7 -5
- data/lib/shrine/plugins/upload_options.rb +18 -4
- data/lib/shrine/plugins/url_options.rb +17 -3
- data/lib/shrine/plugins/validation.rb +8 -8
- data/lib/shrine/plugins/validation_helpers.rb +2 -2
- data/lib/shrine/plugins/versions.rb +10 -10
- data/lib/shrine/plugins.rb +6 -14
- data/lib/shrine/storage/file_system.rb +15 -19
- data/lib/shrine/storage/linter.rb +8 -8
- data/lib/shrine/storage/memory.rb +1 -3
- data/lib/shrine/storage/s3.rb +60 -40
- data/lib/shrine/uploaded_file.rb +23 -19
- data/lib/shrine/version.rb +1 -1
- data/lib/shrine.rb +24 -20
- data/shrine.gemspec +10 -8
- metadata +52 -26
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5601661d53737bf3290ec5897dc9d33cfe5edac60a7468e67de7191649671a14
|
|
4
|
+
data.tar.gz: bf2a26e2162a0c1805f2e8d174128e8ee5008060fdbbb9b8e358d41bfdf680a2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7eb43ca8a78d4dedec0d24422ca4bc9f62eb6e454aa61ac7871760c4c398973a9787591295c39799f6b3250d4b3af9e80f7082c659fb6ed67435d775846ca5e2
|
|
7
|
+
data.tar.gz: 636a7343486f6baaa3fa841abcef8439eb0df5d7183d6ac39a756a508de544dd356bca2562a9e01ac76b871a29455d2a40601f8086e8050dcc793bd57fc568e0
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,99 @@
|
|
|
1
|
+
## 3.10.0 (2026-09-20)
|
|
2
|
+
|
|
3
|
+
* Add `fallback_storage` plugin for reading files from a secondary storage when they're missing in the primary storage (@yegorov, @janko)
|
|
4
|
+
|
|
5
|
+
* `data_uri` – Add `:max_size` option for limiting the size of the data URI content, checked before the content is decoded (@jalrax, @janko)
|
|
6
|
+
|
|
7
|
+
* `data_uri` – Pass the error to the `:error_message` proc as an optional second argument (@jalrax, @janko)
|
|
8
|
+
|
|
9
|
+
## 3.9.0 (2026-07-13)
|
|
10
|
+
|
|
11
|
+
* `Shrine.find_storage` now raises `Shrine::MissingStorage` (subclass of `Shrine::Error`) when the storage isn't registered, so it can be rescued separately (@janko)
|
|
12
|
+
|
|
13
|
+
* `url_options` – Allow regular expression storage keys for compatibility with `dynamic_storage` plugin (@janko)
|
|
14
|
+
|
|
15
|
+
* `upload_options` – Allow regular expression storage keys for compatibility with `dynamic_storage` plugin (@janko)
|
|
16
|
+
|
|
17
|
+
* `remove_invalid` – Fix model attribute not being cleared/reverted after deassigning invalid file (@janko)
|
|
18
|
+
|
|
19
|
+
* `activerecord`/`sequel` – Skip deleting the previous attachment when the record being saved was just created, to avoid deleting the original attachment of a duplicated record (@janko)
|
|
20
|
+
|
|
21
|
+
* `tempfile` – Allow `UploadedFile#tempfile` to be called without opening the uploaded file first (@janko)
|
|
22
|
+
|
|
23
|
+
* `activerecord` – Add `:attribute_types` option for skipping serialization of JSON/JSONB attributes declared via the Attributes API, not just database columns (@vojtad, @janko)
|
|
24
|
+
|
|
25
|
+
## 3.8.0 (2026-06-24)
|
|
26
|
+
|
|
27
|
+
* `s3` – Use single-request uploads for smaller files again instead of always using multipart uploads (@janko)
|
|
28
|
+
|
|
29
|
+
* `derivatives` – Forward `Attacher#promote` options to `Attacher#upload_derivatives` (@milkcocoa)
|
|
30
|
+
|
|
31
|
+
* `file_system` – Prevent path traversal outside of the storage directory (@janko)
|
|
32
|
+
|
|
33
|
+
## 3.7.1 (2026-06-03)
|
|
34
|
+
|
|
35
|
+
* Update method signatures of some plugins to work around a Bootsnap bug causing a `wrong number of arguments` error (@janko)
|
|
36
|
+
|
|
37
|
+
* `derivation_endpoint` – Add `:format` argument to `UploadedFile#derivation_url` for path extension (@janko)
|
|
38
|
+
|
|
39
|
+
* `rack_response` – Add `:etag` argument for setting a custom `ETag` (@camilohollanda)
|
|
40
|
+
|
|
41
|
+
## 3.7.0 (2026-05-27)
|
|
42
|
+
|
|
43
|
+
* `rack_response` - Add `:etag` option for setting a custom `ETag` header (@janko)
|
|
44
|
+
|
|
45
|
+
* `download_endpoint` - Add support for expiring URLs (@davidwessman)
|
|
46
|
+
|
|
47
|
+
* `s3` - Use `TransferManager` where available instead of deprecated `upload_steam` (@danieldevlewis)
|
|
48
|
+
|
|
49
|
+
* `column` - Don't attempt to deserialize empty string as JSON (@adam12)
|
|
50
|
+
|
|
51
|
+
* `derivatives` - Add `:keep_derivatives` plugin option to keep existing derivatives when a new file is attached (@fnordfish)
|
|
52
|
+
|
|
53
|
+
* `refresh_metadata` - Add `replace:` keyword argument to `refresh_metadata!` for replacing instead of merging existing metadata (@JacobGalati)
|
|
54
|
+
|
|
55
|
+
* `backgrounding` - Fix options not being forwarded from `promote_cached` to `promote_block` (@4ndypanda)
|
|
56
|
+
|
|
57
|
+
* Fix URI default parser warnings in `UploadedFile` (@adam12)
|
|
58
|
+
|
|
59
|
+
* Drop support for Ruby < 3.2
|
|
60
|
+
|
|
61
|
+
## 3.6.0 (2024-04-29)
|
|
62
|
+
|
|
63
|
+
* Add Rack 3 support (@tomasc, @janko)
|
|
64
|
+
|
|
65
|
+
* Make a copy of attacher context hash when duplicating the attacher (@reidab)
|
|
66
|
+
|
|
67
|
+
* An uploaded file can be implicitly re-opened after it has been closed (@jrochkind)
|
|
68
|
+
|
|
69
|
+
* Add new `:copy_options` for initializing the S3 storage (@hkdahal)
|
|
70
|
+
|
|
71
|
+
## 3.5.0 (2023-07-06)
|
|
72
|
+
|
|
73
|
+
* Migrate website to Docusaurus v2 (@janko)
|
|
74
|
+
|
|
75
|
+
* `download_endpoint` – Return `400 Bad Request` response when serialized file component is invalid (@janko)
|
|
76
|
+
|
|
77
|
+
* `base` – Stop using obsolete `URI.regexp` in `UploadedFile#extension` (@y-yagi)
|
|
78
|
+
|
|
79
|
+
* `s3` – Add `:encoding` option to `S3#open` to be passed to `Down::ChunkedIO#initialize` (@pond)
|
|
80
|
+
|
|
81
|
+
* `s3` – Add `:max_multipart_parts` option for changing default limit of 10,000 parts (@jpl)
|
|
82
|
+
|
|
83
|
+
* `s3` – Don't inherit S3 object tags when copying from temporary to permanent storage (@jrochkind)
|
|
84
|
+
|
|
85
|
+
* `infer_extension` – Add `infer_extension` instance method to the uploader for convenience (@aried3r)
|
|
86
|
+
|
|
87
|
+
* `derivation_endpoint` – Add `:signer` plugin option for providing a custom URL signer (@thibaudgg)
|
|
88
|
+
|
|
89
|
+
* `derivatives` – Don't leak `versions_compatibility: true` setting into other uploaders (@janko)
|
|
90
|
+
|
|
91
|
+
* `derivatives` – Add `:mutex` plugin option for skipping mutex and making attacher marshallable (@janko)
|
|
92
|
+
|
|
93
|
+
* `remove_attachment` – Fix passing boolean values being broken in Ruby 3.2 (@janko)
|
|
94
|
+
|
|
95
|
+
* `model` – When duplicating a record, make the duplicated attacher reference the duplicated record (@janko)
|
|
96
|
+
|
|
1
97
|
## 3.4.0 (2021-06-14)
|
|
2
98
|
|
|
3
99
|
* `base` – Fix passing options to `Shrine.Attachment` on Ruby 3.0 (@lucianghinda)
|
data/README.md
CHANGED
|
@@ -20,20 +20,20 @@ guide]**.
|
|
|
20
20
|
|
|
21
21
|
## Links
|
|
22
22
|
|
|
23
|
-
| Resource
|
|
24
|
-
| :----------------
|
|
25
|
-
| Website & Documentation
|
|
26
|
-
| Demo code
|
|
27
|
-
| Wiki
|
|
28
|
-
|
|
|
23
|
+
| Resource | URL |
|
|
24
|
+
| :---------------- | :----------------------------------------------------------------------------- |
|
|
25
|
+
| Website & Documentation | [shrinerb.com](https://shrinerb.com) |
|
|
26
|
+
| Demo code | [Roda][roda demo] / [Rails][rails demo] |
|
|
27
|
+
| Wiki | [github.com/shrinerb/shrine/wiki](https://github.com/shrinerb/shrine/wiki) |
|
|
28
|
+
| Discussion forum | [github.com/shrinerb/shrine/discussions](https://github.com/shrinerb/shrine/discussions) |
|
|
29
|
+
| Alternate Discussion forum | [discourse.shrinerb.com](https://discourse.shrinerb.com) |
|
|
29
30
|
|
|
30
31
|
## Setup
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
Run:
|
|
33
34
|
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
gem "shrine", "~> 3.0"
|
|
35
|
+
```sh
|
|
36
|
+
bundle add shrine
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
Then add `config/initializers/shrine.rb` which sets up the storage and loads
|
|
@@ -80,7 +80,7 @@ allow users to upload files:
|
|
|
80
80
|
|
|
81
81
|
```erb
|
|
82
82
|
<%= form_for @photo do |f| %>
|
|
83
|
-
<%= f.hidden_field :image, value: @photo.cached_image_data %>
|
|
83
|
+
<%= f.hidden_field :image, value: @photo.cached_image_data, id: nil %>
|
|
84
84
|
<%= f.file_field :image %>
|
|
85
85
|
<%= f.submit %>
|
|
86
86
|
<% end %>
|
data/doc/advantages.md
CHANGED
|
@@ -412,7 +412,7 @@ on top of Rack, so that they can be used with any Ruby web framework.
|
|
|
412
412
|
[Sequel]: http://sequel.jeremyevans.net
|
|
413
413
|
[ROM]: http://rom-rb.org
|
|
414
414
|
[Hanami::Model]: https://github.com/hanami/model
|
|
415
|
-
[plugin system]: https://
|
|
415
|
+
[plugin system]: https://janko.io/the-plugin-system-of-sequel-and-roda/
|
|
416
416
|
[Down]: https://github.com/janko/down
|
|
417
417
|
[ContentDisposition]: https://github.com/shrinerb/content_disposition
|
|
418
418
|
[`file`]: http://linux.die.net/man/1/file
|
data/doc/attacher.md
CHANGED
|
@@ -189,7 +189,7 @@ attacher.upload(file, location: "path/to/file") # setting upload locat
|
|
|
189
189
|
|
|
190
190
|
### Changes
|
|
191
191
|
|
|
192
|
-
When a new file is attached, calling [`Attacher#finalize`](#
|
|
192
|
+
When a new file is attached, calling [`Attacher#finalize`](#finalizing) will
|
|
193
193
|
perform additional actions such as promotion and deleting any previous file.
|
|
194
194
|
It will also trigger [validation].
|
|
195
195
|
|
data/doc/carrierwave.md
CHANGED
|
@@ -368,7 +368,7 @@ Now you should be able to rewrite your application so that it uses Shrine
|
|
|
368
368
|
instead of CarrierWave (you can consult the reference in the next section). You
|
|
369
369
|
can remove the `CarrierwaveShrineSynchronization` module as well.
|
|
370
370
|
|
|
371
|
-
### 5.
|
|
371
|
+
### 5. Backfill metadata
|
|
372
372
|
|
|
373
373
|
You'll notice that Shrine metadata will be absent from the migrated files'
|
|
374
374
|
data. You can run a script that will fill in any missing metadata defined in
|
|
@@ -646,7 +646,7 @@ Shrine.plugin :cached_attachment_data
|
|
|
646
646
|
```
|
|
647
647
|
```rb
|
|
648
648
|
form_for @photo do |f|
|
|
649
|
-
f.hidden_field :image, value: @photo.cached_image_data
|
|
649
|
+
f.hidden_field :image, value: @photo.cached_image_data, id: nil
|
|
650
650
|
f.file_field :image
|
|
651
651
|
end
|
|
652
652
|
```
|
data/doc/changing_derivatives.md
CHANGED
|
@@ -36,7 +36,8 @@ derivatives generated). Let's assume you're generating image thumbnails:
|
|
|
36
36
|
|
|
37
37
|
```rb
|
|
38
38
|
# Gemfile
|
|
39
|
-
gem "image_processing", "~>
|
|
39
|
+
gem "image_processing", "~> 2.0"
|
|
40
|
+
gem "mini_magick", "~> 5.0"
|
|
40
41
|
```
|
|
41
42
|
```rb
|
|
42
43
|
require "image_processing/mini_magick"
|
data/doc/changing_location.md
CHANGED
|
@@ -3,7 +3,7 @@ id: changing-location
|
|
|
3
3
|
title: Migrating File Locations
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
This guide shows how to migrate the location of uploaded files on the same
|
|
6
|
+
This guide shows how to migrate the location of uploaded files on the same
|
|
7
7
|
storage in production, with zero downtime.
|
|
8
8
|
|
|
9
9
|
Let's assume we have a `Photo` model with an `image` file attachment:
|
|
@@ -31,20 +31,32 @@ to work with the previously stored urls because the files have not been migrated
|
|
|
31
31
|
```rb
|
|
32
32
|
class ImageUploader < Shrine
|
|
33
33
|
def generate_location(io, **options)
|
|
34
|
-
# change location generation
|
|
34
|
+
# change location generation, eg....
|
|
35
|
+
[
|
|
36
|
+
options[:record] && options[:record].class.name.underscore,
|
|
37
|
+
option[:record] && options[:record].id,
|
|
38
|
+
super
|
|
39
|
+
].compact.join("/")
|
|
35
40
|
end
|
|
36
41
|
end
|
|
37
42
|
```
|
|
38
43
|
|
|
39
|
-
We can now deploy this change to production so new file uploads will be stored in
|
|
44
|
+
We can now deploy this change to production so new file uploads will be stored in
|
|
40
45
|
the new location.
|
|
41
46
|
|
|
47
|
+
As seen above, we can call `super` to get the include the default location, which uses ruby
|
|
48
|
+
`SecureRandom.hex` to have a unique immutable storage location. While it isn't
|
|
49
|
+
strictly required to have a unique immutable storage location, it makes many
|
|
50
|
+
things work smoother when different content will get a different storage location,
|
|
51
|
+
and is recommended. One approach is using fixed directory/prefix as above.
|
|
52
|
+
|
|
53
|
+
|
|
42
54
|
## 2. Move existing files
|
|
43
55
|
|
|
44
56
|
To move existing files to new location, run the following script. It fetches
|
|
45
57
|
the photos in batches, downloads the image, and re-uploads it to the new location.
|
|
46
|
-
|
|
47
|
-
|
|
58
|
+
Only the files in `:store` storage need to be migrated as the files in `:cache`
|
|
59
|
+
storage will be uploaded to the new location on promotion.
|
|
48
60
|
|
|
49
61
|
```rb
|
|
50
62
|
Photo.find_each do |photo|
|
|
@@ -99,11 +111,12 @@ class MoveFilesJob
|
|
|
99
111
|
|
|
100
112
|
attacher = attacher_class.retrieve(model: record, name: name, file: file_data)
|
|
101
113
|
old_attacher = attacher.dup
|
|
114
|
+
current_file = old_attacher.file
|
|
102
115
|
|
|
103
116
|
attacher.set attacher.upload(attacher.file)
|
|
104
117
|
attacher.set_derivatives attacher.upload_derivatives(attacher.derivatives)
|
|
105
118
|
|
|
106
|
-
attacher.atomic_persist
|
|
119
|
+
attacher.atomic_persist(current_file)
|
|
107
120
|
old_attacher.destroy_attached
|
|
108
121
|
rescue Shrine::AttachmentChanged, ActiveRecord::RecordNotFound
|
|
109
122
|
attacher&.destroy_attached
|
data/doc/design.md
CHANGED
|
@@ -9,8 +9,8 @@ There are five main types of classes that you deal with in Shrine:
|
|
|
9
9
|
|
|
10
10
|
| Class | Description |
|
|
11
11
|
| :---- | :---------- |
|
|
12
|
-
| [`Shrine::Storage::*`](#
|
|
13
|
-
| [`Shrine`](#
|
|
12
|
+
| [`Shrine::Storage::*`](#storage) | Manages files on a particular storage service |
|
|
13
|
+
| [`Shrine`](#shrine) | Wraps uploads and handles loading plugins |
|
|
14
14
|
| [`Shrine::UploadedFile`](#shrineuploadedfile) | Represents a file uploaded to a storage |
|
|
15
15
|
| [`Shrine::Attacher`](#shrineattacher) | Handles file attachment logic |
|
|
16
16
|
| [`Shrine::Attachment`](#shrineattachment) | Provides convenience model attachment interface |
|
|
@@ -60,7 +60,7 @@ end
|
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
Storages are typically not used directly, but through [`Shrine`](#shrine) and
|
|
63
|
-
[`Shrine::UploadedFile`](#
|
|
63
|
+
[`Shrine::UploadedFile`](#shrineuploadedfile) classes.
|
|
64
64
|
|
|
65
65
|
## `Shrine`
|
|
66
66
|
|
|
@@ -264,7 +264,7 @@ When a persistence plugin is loaded ([`activerecord`][activerecord],
|
|
|
264
264
|
[Using Attacher]: https://shrinerb.com/docs/attacher
|
|
265
265
|
[Notes on study of shrine implementation]: https://bibwild.wordpress.com/2018/09/12/notes-on-study-of-shrine-implementation/
|
|
266
266
|
[Creating a New Plugin]: https://shrinerb.com/docs/creating-plugins
|
|
267
|
-
[Plugin system of Sequel and Roda]: https://
|
|
267
|
+
[Plugin system of Sequel and Roda]: https://janko.io/the-plugin-system-of-sequel-and-roda/
|
|
268
268
|
[entity]: https://shrinerb.com/docs/plugins/entity
|
|
269
269
|
[model]: https://shrinerb.com/docs/plugins/model
|
|
270
270
|
[activerecord]: https://shrinerb.com/docs/plugins/activerecord
|
data/doc/external/articles.md
CHANGED
|
@@ -4,22 +4,22 @@ title: Articles
|
|
|
4
4
|
|
|
5
5
|
## Official articles
|
|
6
6
|
|
|
7
|
-
| Article
|
|
8
|
-
| :-------
|
|
9
|
-
| [Better File Uploads with Shrine: Eager Processing](https://
|
|
10
|
-
| [Shrine 3.0 Released](https://
|
|
11
|
-
| [Upcoming Features in Shrine 3.0](https://
|
|
12
|
-
| [Better File Uploads with Shrine: Direct Uploads](https://
|
|
13
|
-
| [Better File Uploads with Shrine: Metadata](https://
|
|
14
|
-
| [Better File Uploads with Shrine: Processing](https://
|
|
15
|
-
| [Better File Uploads with Shrine: Attachment](https://
|
|
16
|
-
| [Better File Uploads with Shrine: Uploader](https://
|
|
17
|
-
| [Better File Uploads with Shrine: Motivation](https://
|
|
18
|
-
| [Resumable File Uploads in Ruby](https://
|
|
19
|
-
| [Shrine meets Transloadit](https://
|
|
20
|
-
| [Shrine 2.0 Released](https://
|
|
21
|
-
| [Asynchronous File Uploads](http://
|
|
22
|
-
| [Introducing Shrine](http://
|
|
7
|
+
| Article | Published |
|
|
8
|
+
| :------- | --------: |
|
|
9
|
+
| [Better File Uploads with Shrine: Eager Processing](https://janko.io/better-file-uploads-with-shrine-eager-processing/) | 12 Dec 2019 |
|
|
10
|
+
| [Shrine 3.0 Released](https://janko.io/shrine-3-0-released/) | 14 Oct 2019 |
|
|
11
|
+
| [Upcoming Features in Shrine 3.0](https://janko.io/upcoming-features-in-shrine-3-0/) | 29 Aug 2019 |
|
|
12
|
+
| [Better File Uploads with Shrine: Direct Uploads](https://janko.io/better-file-uploads-with-shrine-direct-uploads/) | 08 Jan 2018 |
|
|
13
|
+
| [Better File Uploads with Shrine: Metadata](https://janko.io/better-file-uploads-with-shrine-metadata/) | 07 Nov 2016 |
|
|
14
|
+
| [Better File Uploads with Shrine: Processing](https://janko.io/better-file-uploads-with-shrine-processing/) | 31 Oct 2016 |
|
|
15
|
+
| [Better File Uploads with Shrine: Attachment](https://janko.io/better-file-uploads-with-shrine-attachment/) | 17 Sep 2016 |
|
|
16
|
+
| [Better File Uploads with Shrine: Uploader](https://janko.io/better-file-uploads-with-shrine-uploader/) | 16 Sep 2016 |
|
|
17
|
+
| [Better File Uploads with Shrine: Motivation](https://janko.io/better-file-uploads-with-shrine-motivation/) | 11 Sep 2016 |
|
|
18
|
+
| [Resumable File Uploads in Ruby](https://janko.io/resumable-file-uploads-in-ruby/) | 04 Sep 2016 |
|
|
19
|
+
| [Shrine meets Transloadit](https://janko.io/shrine-meets-transloadit/) | 11 Jul 2016 |
|
|
20
|
+
| [Shrine 2.0 Released](https://janko.io/shrine-2-0-released/) | 20 May 2016 |
|
|
21
|
+
| [Asynchronous File Uploads](http://janko.io/file-uploads-asynchronous-world) | 18 Jan 2016 |
|
|
22
|
+
| [Introducing Shrine](http://janko.io/introducing-shrine) | 04 Oct 2015 |
|
|
23
23
|
|
|
24
24
|
## Community articles
|
|
25
25
|
|
data/doc/external/extensions.md
CHANGED
|
@@ -35,7 +35,7 @@ title: Extensions
|
|
|
35
35
|
| [shrine-content_addressable](https://github.com/SleeplessByte/shrine-content_addressable) | Plugin for generating content addressable locations |
|
|
36
36
|
| [shrine-imgix](https://github.com/shrinerb/shrine-imgix) | Plugin for [Imgix](https://www.imgix.com/) |
|
|
37
37
|
| [shrine-transloadit](https://github.com/shrinerb/shrine-transloadit) | Plugin for [Transloadit](https://transloadit.com/) |
|
|
38
|
-
| [shrine-lambda](https://github.com/texpert/shrine-lambda)
|
|
38
|
+
| [shrine-aws-lambda](https://github.com/texpert/shrine-aws-lambda) | Plugin for [AWS Lambda](https://aws.amazon.com/lambda/) |
|
|
39
39
|
| [hanami-shrine](https://github.com/katafrakt/hanami-shrine) | Plugin for [Hanami](https://hanamirb.org/) |
|
|
40
40
|
| [shrine-mongoid](https://github.com/shrinerb/shrine-mongoid) | Plugin for [Mongoid](https://mongoid.org) |
|
|
41
41
|
| [shrine-rails](https://github.com/abepetrillo/shrine-rails) | Plugin for [Rails](https://rubyonrails.org/) |
|
data/doc/getting_started.md
CHANGED
|
@@ -3,6 +3,9 @@ id: getting-started
|
|
|
3
3
|
title: Getting Started
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
import Tabs from '@theme/Tabs';
|
|
7
|
+
import TabItem from '@theme/TabItem';
|
|
8
|
+
|
|
6
9
|
## Quick start
|
|
7
10
|
|
|
8
11
|
Add Shrine to the Gemfile and write an initializer which sets up the storage
|
|
@@ -32,32 +35,39 @@ Next decide how you will name the attachment attribute on your model, and run a
|
|
|
32
35
|
migration that adds an `<attachment>_data` text or JSON column, which Shrine
|
|
33
36
|
will use to store all information about the attachment:
|
|
34
37
|
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
<Tabs>
|
|
39
|
+
<TabItem value="sequel" label="Sequel">
|
|
40
|
+
|
|
37
41
|
```rb
|
|
38
42
|
Sequel.migration do
|
|
39
43
|
change do
|
|
40
|
-
add_column :photos, :image_data, :text # or :jsonb
|
|
44
|
+
add_column :photos, :image_data, :text # or :jsonb
|
|
41
45
|
end
|
|
42
46
|
end
|
|
43
47
|
```
|
|
44
48
|
|
|
45
|
-
|
|
49
|
+
</TabItem>
|
|
50
|
+
<TabItem value="activerecord" label="Active Record">
|
|
51
|
+
|
|
46
52
|
```rb
|
|
47
53
|
class AddImageDataToPhotos < ActiveRecord::Migration
|
|
48
54
|
def change
|
|
49
|
-
add_column :photos, :image_data, :text # or :jsonb
|
|
55
|
+
add_column :photos, :image_data, :text # or :jsonb
|
|
50
56
|
end
|
|
51
57
|
end
|
|
52
58
|
```
|
|
53
59
|
|
|
54
|
-
|
|
60
|
+
</TabItem>
|
|
61
|
+
<TabItem value="rails" label="Rails">
|
|
62
|
+
|
|
55
63
|
```rb
|
|
56
|
-
$ rails generate migration add_image_data_to_photos image_data:text
|
|
64
|
+
$ rails generate migration add_image_data_to_photos image_data:text # or image_data:jsonb
|
|
57
65
|
```
|
|
58
|
-
If using `jsonb` consider adding a [gin index] for fast key-value pair searchability within `image_data`.
|
|
59
66
|
|
|
60
|
-
|
|
67
|
+
</TabItem>
|
|
68
|
+
</Tabs>
|
|
69
|
+
|
|
70
|
+
If using `jsonb` consider adding a [gin index] for fast key-value pair searchability within `image_data`.
|
|
61
71
|
|
|
62
72
|
Now you can create an uploader class for the type of files you want to upload,
|
|
63
73
|
and add a virtual attribute for handling attachments using this uploader to
|
|
@@ -69,36 +79,47 @@ class ImageUploader < Shrine
|
|
|
69
79
|
# plugins and uploading logic
|
|
70
80
|
end
|
|
71
81
|
```
|
|
72
|
-
|
|
73
|
-
|
|
82
|
+
|
|
83
|
+
<Tabs>
|
|
84
|
+
<TabItem value="sequel" label="Sequel">
|
|
85
|
+
|
|
74
86
|
```rb
|
|
75
87
|
class Photo < Sequel::Model
|
|
76
88
|
include ImageUploader::Attachment(:image) # adds an `image` virtual attribute
|
|
77
89
|
end
|
|
78
90
|
```
|
|
79
|
-
|
|
91
|
+
|
|
92
|
+
</TabItem>
|
|
93
|
+
<TabItem value="activerecord" label="Active Record">
|
|
94
|
+
|
|
80
95
|
```rb
|
|
81
96
|
class Photo < ActiveRecord::Base
|
|
82
97
|
include ImageUploader::Attachment(:image) # adds an `image` virtual attribute
|
|
83
98
|
end
|
|
84
99
|
```
|
|
85
|
-
|
|
100
|
+
|
|
101
|
+
</TabItem>
|
|
102
|
+
</Tabs>
|
|
86
103
|
|
|
87
104
|
Let's now add the form fields which will use this virtual attribute (NOT the
|
|
88
105
|
`<attachment>_data` column attribute). We need (1) a file field for choosing
|
|
89
106
|
files, and (2) a hidden field for retaining the uploaded file in case of
|
|
90
107
|
validation errors and for potential [direct uploads].
|
|
91
108
|
|
|
92
|
-
|
|
93
|
-
|
|
109
|
+
<Tabs>
|
|
110
|
+
<TabItem value="rails" label="Rails form builder">
|
|
111
|
+
|
|
94
112
|
```rb
|
|
95
113
|
form_for @photo do |f|
|
|
96
|
-
f.hidden_field :image, value: @photo.cached_image_data
|
|
114
|
+
f.hidden_field :image, value: @photo.cached_image_data, id: nil
|
|
97
115
|
f.file_field :image
|
|
98
116
|
f.submit
|
|
99
117
|
end
|
|
100
118
|
```
|
|
101
|
-
|
|
119
|
+
|
|
120
|
+
</TabItem>
|
|
121
|
+
<TabItem value="simple_form" label="Simple Form">
|
|
122
|
+
|
|
102
123
|
```rb
|
|
103
124
|
simple_form_for @photo do |f|
|
|
104
125
|
f.input :image, as: :hidden, input_html: { value: @photo.cached_image_data }
|
|
@@ -106,7 +127,10 @@ simple_form_for @photo do |f|
|
|
|
106
127
|
f.button :submit
|
|
107
128
|
end
|
|
108
129
|
```
|
|
109
|
-
|
|
130
|
+
|
|
131
|
+
</TabItem>
|
|
132
|
+
<TabItem value="form" label="Forme">
|
|
133
|
+
|
|
110
134
|
```rb
|
|
111
135
|
form @photo, action: "/photos", enctype: "multipart/form-data" do |f|
|
|
112
136
|
f.input :image, type: :hidden, value: @photo.cached_image_data
|
|
@@ -114,7 +138,10 @@ form @photo, action: "/photos", enctype: "multipart/form-data" do |f|
|
|
|
114
138
|
f.button "Create"
|
|
115
139
|
end
|
|
116
140
|
```
|
|
117
|
-
|
|
141
|
+
|
|
142
|
+
</TabItem>
|
|
143
|
+
<TabItem value="html" label="HTML">
|
|
144
|
+
|
|
118
145
|
```erb
|
|
119
146
|
<form action="/photos" method="post" enctype="multipart/form-data">
|
|
120
147
|
<input name="photo[image]" type="hidden" value="<%= @photo.cached_image_data %>" />
|
|
@@ -122,7 +149,9 @@ end
|
|
|
122
149
|
<input type="submit" value="Create" />
|
|
123
150
|
</form>
|
|
124
151
|
```
|
|
125
|
-
|
|
152
|
+
|
|
153
|
+
</TabItem>
|
|
154
|
+
</Tabs>
|
|
126
155
|
|
|
127
156
|
Note that the file field needs to go *after* the hidden field, so that
|
|
128
157
|
selecting a new file can always override the cached file in the hidden field.
|
|
@@ -133,8 +162,9 @@ will automatically generate this for you).
|
|
|
133
162
|
When the form is submitted, in your router/controller you can assign the file
|
|
134
163
|
from request params to the attachment attribute on the model.
|
|
135
164
|
|
|
136
|
-
|
|
137
|
-
|
|
165
|
+
<Tabs>
|
|
166
|
+
<TabItem value="rails" label="Rails">
|
|
167
|
+
|
|
138
168
|
```rb
|
|
139
169
|
class PhotosController < ApplicationController
|
|
140
170
|
def create
|
|
@@ -149,28 +179,39 @@ class PhotosController < ApplicationController
|
|
|
149
179
|
end
|
|
150
180
|
end
|
|
151
181
|
```
|
|
152
|
-
|
|
182
|
+
|
|
183
|
+
</TabItem>
|
|
184
|
+
<TabItem value="sinatra" label="Sinatra">
|
|
185
|
+
|
|
153
186
|
```rb
|
|
154
187
|
post "/photos" do
|
|
155
188
|
Photo.create(params[:photo])
|
|
156
189
|
# ...
|
|
157
190
|
end
|
|
158
191
|
```
|
|
159
|
-
|
|
192
|
+
|
|
193
|
+
</TabItem>
|
|
194
|
+
</Tabs>
|
|
160
195
|
|
|
161
196
|
Once a file is uploaded and attached to the record, you can retrieve a URL to
|
|
162
197
|
the uploaded file with `#<attachment>_url` and display it on the page:
|
|
163
198
|
|
|
164
|
-
|
|
165
|
-
|
|
199
|
+
<Tabs>
|
|
200
|
+
<TabItem value="rails" label="Rails">
|
|
201
|
+
|
|
166
202
|
```erb
|
|
167
203
|
<%= image_tag @photo.image_url %>
|
|
168
204
|
```
|
|
169
|
-
|
|
205
|
+
|
|
206
|
+
</TabItem>
|
|
207
|
+
<TabItem value="html" label="HTML">
|
|
208
|
+
|
|
170
209
|
```erb
|
|
171
210
|
<img src="<%= @photo.image_url %>" />
|
|
172
211
|
```
|
|
173
|
-
|
|
212
|
+
|
|
213
|
+
</TabItem>
|
|
214
|
+
</Tabs>
|
|
174
215
|
|
|
175
216
|
## Storage
|
|
176
217
|
|
|
@@ -561,7 +602,8 @@ creation:
|
|
|
561
602
|
|
|
562
603
|
```rb
|
|
563
604
|
# Gemfile
|
|
564
|
-
gem "image_processing", "~>
|
|
605
|
+
gem "image_processing", "~> 2.0"
|
|
606
|
+
gem "mini_magick", "~> 5.0"
|
|
565
607
|
```
|
|
566
608
|
```rb
|
|
567
609
|
Shrine.plugin :derivatives, create_on_promote: true
|
|
@@ -615,7 +657,8 @@ processing we want to perform:
|
|
|
615
657
|
|
|
616
658
|
```rb
|
|
617
659
|
# Gemfile
|
|
618
|
-
gem "image_processing", "~>
|
|
660
|
+
gem "image_processing", "~> 2.0"
|
|
661
|
+
gem "mini_magick", "~> 5.0"
|
|
619
662
|
```
|
|
620
663
|
```rb
|
|
621
664
|
# config/initializers/rails.rb (Rails)
|