shrine 3.3.0 → 3.5.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 +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
|