shrine 3.3.0 → 3.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +42 -0
- data/README.md +14 -12
- data/doc/carrierwave.md +2 -2
- data/doc/changing_derivatives.md +1 -1
- data/doc/changing_location.md +8 -6
- data/doc/design.md +5 -5
- data/doc/direct_s3.md +25 -0
- data/doc/external/articles.md +16 -16
- data/doc/external/extensions.md +1 -1
- data/doc/getting_started.md +79 -27
- data/doc/metadata.md +1 -1
- data/doc/multiple_files.md +57 -22
- data/doc/paperclip.md +1 -0
- data/doc/plugins/backgrounding.md +4 -4
- data/doc/plugins/derivation_endpoint.md +24 -0
- data/doc/plugins/derivatives.md +11 -1
- data/doc/plugins/entity.md +12 -4
- data/doc/plugins/instrumentation.md +1 -1
- data/doc/plugins/keep_files.md +6 -4
- data/doc/plugins/model.md +8 -3
- data/doc/plugins/sequel.md +1 -1
- data/doc/plugins/validation_helpers.md +1 -1
- data/doc/processing.md +3 -2
- data/doc/refile.md +3 -3
- data/doc/release_notes/2.1.0.md +1 -1
- data/doc/release_notes/3.4.0.md +35 -0
- data/doc/release_notes/3.5.0.md +63 -0
- data/doc/retrieving_uploads.md +1 -1
- data/doc/testing.md +55 -17
- data/doc/upgrading_to_3.md +6 -8
- data/lib/shrine/plugins/activerecord.rb +3 -3
- data/lib/shrine/plugins/derivation_endpoint.rb +31 -30
- data/lib/shrine/plugins/derivatives.rb +25 -19
- data/lib/shrine/plugins/determine_mime_type.rb +2 -0
- data/lib/shrine/plugins/download_endpoint.rb +7 -0
- data/lib/shrine/plugins/entity.rb +14 -7
- data/lib/shrine/plugins/infer_extension.rb +4 -0
- data/lib/shrine/plugins/instrumentation.rb +17 -19
- data/lib/shrine/plugins/model.rb +3 -1
- data/lib/shrine/plugins/remove_attachment.rb +2 -0
- data/lib/shrine/plugins/sequel.rb +1 -1
- data/lib/shrine/plugins/validation_helpers.rb +1 -1
- data/lib/shrine/storage/s3.rb +17 -7
- data/lib/shrine/uploaded_file.rb +3 -2
- data/lib/shrine/version.rb +1 -1
- data/lib/shrine.rb +3 -3
- data/shrine.gemspec +3 -2
- metadata +26 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 46e9fa07aa69797777e3072eed12a4b901b357ae840c71f4facd5b0be2d79929
|
4
|
+
data.tar.gz: 0714e663dd130b9af96b195e5a3d87c128a0e6dd0b0598a7b2d4286e97223008
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 87b70c2bd15dd044eacc1b2089b65bb0538728fd56dea5cce8e6e191b3bf07e63e2af45b877bfd317bcf38c98279c49d07f5d18db28d106cb08360478f1bcb76
|
7
|
+
data.tar.gz: 57703469c6efa1e724113944815dc9fb5e2a3506cf261810c07d0e40c7849bc79d2184bb576222ca7a21c56fe3f496602e93d7b60696cee763aabdaaed71cf23
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,45 @@
|
|
1
|
+
## 3.5.0 (2023-07-06)
|
2
|
+
|
3
|
+
* Migrate website to Docusaurus v2 (@janko)
|
4
|
+
|
5
|
+
* `download_endpoint` – Return `400 Bad Request` response when serialized file component is invalid (@janko)
|
6
|
+
|
7
|
+
* `base` – Stop using obsolete `URI.regexp` in `UploadedFile#extension` (@y-yagi)
|
8
|
+
|
9
|
+
* `s3` – Add `:encoding` option to `S3#open` to be passed to `Down::ChunkedIO#initialize` (@pond)
|
10
|
+
|
11
|
+
* `s3` – Add `:max_multipart_parts` option for changing default limit of 10,000 parts (@jpl)
|
12
|
+
|
13
|
+
* `s3` – Don't inherit S3 object tags when copying from temporary to permanent storage (@jrochkind)
|
14
|
+
|
15
|
+
* `infer_extension` – Add `infer_extension` instance method to the uploader for convenience (@aried3r)
|
16
|
+
|
17
|
+
* `derivation_endpoint` – Add `:signer` plugin option for providing a custom URL signer (@thibaudgg)
|
18
|
+
|
19
|
+
* `derivatives` – Don't leak `versions_compatibility: true` setting into other uploaders (@janko)
|
20
|
+
|
21
|
+
* `derivatives` – Add `:mutex` plugin option for skipping mutex and making attacher marshallable (@janko)
|
22
|
+
|
23
|
+
* `remove_attachment` – Fix passing boolean values being broken in Ruby 3.2 (@janko)
|
24
|
+
|
25
|
+
* `model` – When duplicating a record, make the duplicated attacher reference the duplicated record (@janko)
|
26
|
+
|
27
|
+
## 3.4.0 (2021-06-14)
|
28
|
+
|
29
|
+
* `base` – Fix passing options to `Shrine.Attachment` on Ruby 3.0 (@lucianghinda)
|
30
|
+
|
31
|
+
* `determine_mime_type` – Return correct `image/svg+xml` MIME type for SVGs with `:fastimage` analyzer (@Bandes)
|
32
|
+
|
33
|
+
* `activerecord` – Fix keyword argument warning when adding errors with options (@janko)
|
34
|
+
|
35
|
+
* `entity` – Make `Attacher#read` method public (@janko)
|
36
|
+
|
37
|
+
* `entity` – Reset attachment dirty tracking in `Attacher#reload` (@janko)
|
38
|
+
|
39
|
+
* `activerecord` – Don't load the attacher on `ActiveRecord::Base#reload` if it hasn't yet been initialized (@janko)
|
40
|
+
|
41
|
+
* `sequel` – Don't load the attacher on `Sequel::Model#reload` if it hasn't yet been initialized (@janko)
|
42
|
+
|
1
43
|
## 3.3.0 (2020-10-04)
|
2
44
|
|
3
45
|
* `s3` - Support new `Aws::S3::EncryptionV2::Client` for client-side encryption (@janko)
|
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
|
@@ -57,8 +57,9 @@ Next, add the `<name>_data` column to the table you want to attach files to. For
|
|
57
57
|
an "image" attachment on a `photos` table this would be an `image_data` column:
|
58
58
|
|
59
59
|
```
|
60
|
-
$ rails generate migration add_image_data_to_photos image_data:text
|
60
|
+
$ rails generate migration add_image_data_to_photos image_data:text # or :jsonb
|
61
61
|
```
|
62
|
+
If using `jsonb` consider adding a [gin index] for fast key-value pair searchability within `image_data`.
|
62
63
|
|
63
64
|
Now create an uploader class (which you can put in `app/uploaders`) and
|
64
65
|
register the attachment on your model:
|
@@ -79,7 +80,7 @@ allow users to upload files:
|
|
79
80
|
|
80
81
|
```erb
|
81
82
|
<%= form_for @photo do |f| %>
|
82
|
-
<%= f.hidden_field :image, value: @photo.cached_image_data %>
|
83
|
+
<%= f.hidden_field :image, value: @photo.cached_image_data, id: nil %>
|
83
84
|
<%= f.file_field :image %>
|
84
85
|
<%= f.submit %>
|
85
86
|
<% end %>
|
@@ -175,3 +176,4 @@ The gem is available as open source under the terms of the [MIT License].
|
|
175
176
|
[CoC]: /CODE_OF_CONDUCT.md
|
176
177
|
[MIT License]: /LICENSE.txt
|
177
178
|
[Contributing]: https://github.com/shrinerb/shrine/blob/master/CONTRIBUTING.md
|
179
|
+
[gin index]: https://www.postgresql.org/docs/current/datatype-json.html#JSON-INDEXING
|
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
data/doc/changing_location.md
CHANGED
@@ -53,16 +53,17 @@ Photo.find_each do |photo|
|
|
53
53
|
next unless attacher.stored? # move only attachments uploaded to permanent storage
|
54
54
|
|
55
55
|
old_attacher = attacher.dup
|
56
|
+
current_file = old_attacher.file
|
56
57
|
|
57
58
|
attacher.set attacher.upload(attacher.file) # reupload file
|
58
59
|
attacher.set_derivatives attacher.upload_derivatives(attacher.derivatives) # reupload derivatives if you have derivatives
|
59
60
|
|
60
61
|
begin
|
61
|
-
attacher.atomic_persist
|
62
|
-
old_attacher.destroy_attached
|
63
|
-
rescue Shrine::AttachmentChanged,
|
64
|
-
ActiveRecord::RecordNotFound
|
65
|
-
attacher.destroy_attached
|
62
|
+
attacher.atomic_persist(current_file) # persist changes if attachment has not changed in the meantime
|
63
|
+
old_attacher.destroy_attached # delete files on old location
|
64
|
+
rescue Shrine::AttachmentChanged, # attachment has changed during reuploading
|
65
|
+
ActiveRecord::RecordNotFound # record has been deleted during reuploading
|
66
|
+
attacher.destroy_attached # delete now orphaned files
|
66
67
|
end
|
67
68
|
end
|
68
69
|
```
|
@@ -98,11 +99,12 @@ class MoveFilesJob
|
|
98
99
|
|
99
100
|
attacher = attacher_class.retrieve(model: record, name: name, file: file_data)
|
100
101
|
old_attacher = attacher.dup
|
102
|
+
current_file = old_attacher.file
|
101
103
|
|
102
104
|
attacher.set attacher.upload(attacher.file)
|
103
105
|
attacher.set_derivatives attacher.upload_derivatives(attacher.derivatives)
|
104
106
|
|
105
|
-
attacher.atomic_persist
|
107
|
+
attacher.atomic_persist(current_file)
|
106
108
|
old_attacher.destroy_attached
|
107
109
|
rescue Shrine::AttachmentChanged, ActiveRecord::RecordNotFound
|
108
110
|
attacher&.destroy_attached
|
data/doc/design.md
CHANGED
@@ -9,11 +9,11 @@ There are five main types of classes that you deal with in Shrine:
|
|
9
9
|
|
10
10
|
| Class | Description |
|
11
11
|
| :---- | :---------- |
|
12
|
-
| `Shrine::Storage::*` | Manages files on a particular storage service |
|
13
|
-
| `Shrine` | Wraps uploads and handles loading plugins |
|
14
|
-
| `Shrine::UploadedFile` | Represents a file uploaded to a storage |
|
15
|
-
| `Shrine::Attacher` | Handles file attachment logic |
|
16
|
-
| `Shrine::Attachment` | Provides convenience model attachment interface |
|
12
|
+
| [`Shrine::Storage::*`](#Storage) | Manages files on a particular storage service |
|
13
|
+
| [`Shrine`](#Shrine) | Wraps uploads and handles loading plugins |
|
14
|
+
| [`Shrine::UploadedFile`](#shrineuploadedfile) | Represents a file uploaded to a storage |
|
15
|
+
| [`Shrine::Attacher`](#shrineattacher) | Handles file attachment logic |
|
16
|
+
| [`Shrine::Attachment`](#shrineattachment) | Provides convenience model attachment interface |
|
17
17
|
|
18
18
|
## Storage
|
19
19
|
|
data/doc/direct_s3.md
CHANGED
@@ -86,6 +86,31 @@ If you're using [Uppy], this is the recommended CORS configuration for the
|
|
86
86
|
</CORSConfiguration>
|
87
87
|
```
|
88
88
|
|
89
|
+
Or in JSON format:
|
90
|
+
|
91
|
+
```json
|
92
|
+
[
|
93
|
+
{
|
94
|
+
"AllowedOrigins": [ "https://my-app.com" ],
|
95
|
+
"AllowedMethods": [ "GET", "POST", "PUT" ],
|
96
|
+
"MaxAgeSeconds": 3000,
|
97
|
+
"AllowedHeaders": [
|
98
|
+
"Authorization",
|
99
|
+
"x-amz-date",
|
100
|
+
"x-amz-content-sha256",
|
101
|
+
"Content-Type",
|
102
|
+
"Content-Disposition"
|
103
|
+
],
|
104
|
+
"ExposeHeaders": [ "ETag" ]
|
105
|
+
},
|
106
|
+
{
|
107
|
+
"AllowedOrigins": [ "*" ],
|
108
|
+
"AllowedMethods": [ "GET" ],
|
109
|
+
"MaxAgeSeconds": 3000
|
110
|
+
}
|
111
|
+
]
|
112
|
+
```
|
113
|
+
|
89
114
|
Replace `https://my-app.com` with the URL to your app (in development you can
|
90
115
|
set this to `*`). Once you've hit "Save", it may take some time for the
|
91
116
|
new CORS settings to be applied.
|
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,8 +35,9 @@ 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
|
@@ -41,7 +45,10 @@ Sequel.migration do
|
|
41
45
|
end
|
42
46
|
end
|
43
47
|
```
|
44
|
-
|
48
|
+
|
49
|
+
</TabItem>
|
50
|
+
<TabItem value="activerecord" label="Active Record">
|
51
|
+
|
45
52
|
```rb
|
46
53
|
class AddImageDataToPhotos < ActiveRecord::Migration
|
47
54
|
def change
|
@@ -49,11 +56,18 @@ class AddImageDataToPhotos < ActiveRecord::Migration
|
|
49
56
|
end
|
50
57
|
end
|
51
58
|
```
|
52
|
-
|
53
|
-
|
54
|
-
|
59
|
+
|
60
|
+
</TabItem>
|
61
|
+
<TabItem value="rails" label="Rails">
|
62
|
+
|
63
|
+
```rb
|
64
|
+
$ rails generate migration add_image_data_to_photos image_data:text # or image_data:jsonb
|
55
65
|
```
|
56
|
-
|
66
|
+
|
67
|
+
</TabItem>
|
68
|
+
</Tabs>
|
69
|
+
|
70
|
+
If using `jsonb` consider adding a [gin index] for fast key-value pair searchability within `image_data`.
|
57
71
|
|
58
72
|
Now you can create an uploader class for the type of files you want to upload,
|
59
73
|
and add a virtual attribute for handling attachments using this uploader to
|
@@ -65,36 +79,47 @@ class ImageUploader < Shrine
|
|
65
79
|
# plugins and uploading logic
|
66
80
|
end
|
67
81
|
```
|
68
|
-
|
69
|
-
|
82
|
+
|
83
|
+
<Tabs>
|
84
|
+
<TabItem value="sequel" label="Sequel">
|
85
|
+
|
70
86
|
```rb
|
71
87
|
class Photo < Sequel::Model
|
72
88
|
include ImageUploader::Attachment(:image) # adds an `image` virtual attribute
|
73
89
|
end
|
74
90
|
```
|
75
|
-
|
91
|
+
|
92
|
+
</TabItem>
|
93
|
+
<TabItem value="activerecord" label="Active Record">
|
94
|
+
|
76
95
|
```rb
|
77
96
|
class Photo < ActiveRecord::Base
|
78
97
|
include ImageUploader::Attachment(:image) # adds an `image` virtual attribute
|
79
98
|
end
|
80
99
|
```
|
81
|
-
|
100
|
+
|
101
|
+
</TabItem>
|
102
|
+
</Tabs>
|
82
103
|
|
83
104
|
Let's now add the form fields which will use this virtual attribute (NOT the
|
84
105
|
`<attachment>_data` column attribute). We need (1) a file field for choosing
|
85
106
|
files, and (2) a hidden field for retaining the uploaded file in case of
|
86
107
|
validation errors and for potential [direct uploads].
|
87
108
|
|
88
|
-
|
89
|
-
|
109
|
+
<Tabs>
|
110
|
+
<TabItem value="rails" label="Rails form builder">
|
111
|
+
|
90
112
|
```rb
|
91
113
|
form_for @photo do |f|
|
92
|
-
f.hidden_field :image, value: @photo.cached_image_data
|
114
|
+
f.hidden_field :image, value: @photo.cached_image_data, id: nil
|
93
115
|
f.file_field :image
|
94
116
|
f.submit
|
95
117
|
end
|
96
118
|
```
|
97
|
-
|
119
|
+
|
120
|
+
</TabItem>
|
121
|
+
<TabItem value="simple_form" label="Simple Form">
|
122
|
+
|
98
123
|
```rb
|
99
124
|
simple_form_for @photo do |f|
|
100
125
|
f.input :image, as: :hidden, input_html: { value: @photo.cached_image_data }
|
@@ -102,7 +127,10 @@ simple_form_for @photo do |f|
|
|
102
127
|
f.button :submit
|
103
128
|
end
|
104
129
|
```
|
105
|
-
|
130
|
+
|
131
|
+
</TabItem>
|
132
|
+
<TabItem value="form" label="Forme">
|
133
|
+
|
106
134
|
```rb
|
107
135
|
form @photo, action: "/photos", enctype: "multipart/form-data" do |f|
|
108
136
|
f.input :image, type: :hidden, value: @photo.cached_image_data
|
@@ -110,7 +138,10 @@ form @photo, action: "/photos", enctype: "multipart/form-data" do |f|
|
|
110
138
|
f.button "Create"
|
111
139
|
end
|
112
140
|
```
|
113
|
-
|
141
|
+
|
142
|
+
</TabItem>
|
143
|
+
<TabItem value="html" label="HTML">
|
144
|
+
|
114
145
|
```erb
|
115
146
|
<form action="/photos" method="post" enctype="multipart/form-data">
|
116
147
|
<input name="photo[image]" type="hidden" value="<%= @photo.cached_image_data %>" />
|
@@ -118,7 +149,9 @@ end
|
|
118
149
|
<input type="submit" value="Create" />
|
119
150
|
</form>
|
120
151
|
```
|
121
|
-
|
152
|
+
|
153
|
+
</TabItem>
|
154
|
+
</Tabs>
|
122
155
|
|
123
156
|
Note that the file field needs to go *after* the hidden field, so that
|
124
157
|
selecting a new file can always override the cached file in the hidden field.
|
@@ -129,8 +162,9 @@ will automatically generate this for you).
|
|
129
162
|
When the form is submitted, in your router/controller you can assign the file
|
130
163
|
from request params to the attachment attribute on the model.
|
131
164
|
|
132
|
-
|
133
|
-
|
165
|
+
<Tabs>
|
166
|
+
<TabItem value="rails" label="Rails">
|
167
|
+
|
134
168
|
```rb
|
135
169
|
class PhotosController < ApplicationController
|
136
170
|
def create
|
@@ -145,28 +179,39 @@ class PhotosController < ApplicationController
|
|
145
179
|
end
|
146
180
|
end
|
147
181
|
```
|
148
|
-
|
182
|
+
|
183
|
+
</TabItem>
|
184
|
+
<TabItem value="sinatra" label="Sinatra">
|
185
|
+
|
149
186
|
```rb
|
150
187
|
post "/photos" do
|
151
188
|
Photo.create(params[:photo])
|
152
189
|
# ...
|
153
190
|
end
|
154
191
|
```
|
155
|
-
|
192
|
+
|
193
|
+
</TabItem>
|
194
|
+
</Tabs>
|
156
195
|
|
157
196
|
Once a file is uploaded and attached to the record, you can retrieve a URL to
|
158
197
|
the uploaded file with `#<attachment>_url` and display it on the page:
|
159
198
|
|
160
|
-
|
161
|
-
|
199
|
+
<Tabs>
|
200
|
+
<TabItem value="rails" label="Rails">
|
201
|
+
|
162
202
|
```erb
|
163
203
|
<%= image_tag @photo.image_url %>
|
164
204
|
```
|
165
|
-
|
205
|
+
|
206
|
+
</TabItem>
|
207
|
+
<TabItem value="html" label="HTML">
|
208
|
+
|
166
209
|
```erb
|
167
210
|
<img src="<%= @photo.image_url %>" />
|
168
211
|
```
|
169
|
-
|
212
|
+
|
213
|
+
</TabItem>
|
214
|
+
</Tabs>
|
170
215
|
|
171
216
|
## Storage
|
172
217
|
|
@@ -481,6 +526,12 @@ If you want to extend Shrine functionality with custom behaviour, you can also
|
|
481
526
|
[create your own plugin][Creating Plugins]. There are also additional [external
|
482
527
|
plugins] created by others.
|
483
528
|
|
529
|
+
> NOTE: An uploader class will inherit a copy of current superclass' plugin
|
530
|
+
> options at the time of subclassing. This means you should *not* load
|
531
|
+
> additional plugins on a superclass after the subclass has already been
|
532
|
+
> created, because new options will not get applied to the subclass, which
|
533
|
+
> can result in errors.
|
534
|
+
|
484
535
|
## Metadata
|
485
536
|
|
486
537
|
Shrine automatically extracts some basic file metadata and saves them to the
|
@@ -531,7 +582,7 @@ the [Extracting Metadata] guide for more details.
|
|
531
582
|
|
532
583
|
Shrine allows you to process attached files both "eagerly" and "on-the-fly".
|
533
584
|
For example, if your app is accepting image uploads, you can generate a
|
534
|
-
predefined set of
|
585
|
+
predefined set of thumbnails when the image is attached to a record, or you
|
535
586
|
can have thumbnails generated dynamically as they're needed.
|
536
587
|
|
537
588
|
For image processing, it's recommended to use the **[ImageProcessing]** gem,
|
@@ -1102,3 +1153,4 @@ Shrine.logger.level = Logger::WARN
|
|
1102
1153
|
[storages]: https://shrinerb.com/docs/external/extensions#storages
|
1103
1154
|
[plugins]: https://shrinerb.com/plugins
|
1104
1155
|
[external plugins]: https://shrinerb.com/docs/external/extensions#plugins
|
1156
|
+
[gin index]: https://www.postgresql.org/docs/current/datatype-json.html#JSON-INDEXING
|