shrine 3.3.0 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -0
  3. data/README.md +14 -12
  4. data/doc/carrierwave.md +2 -2
  5. data/doc/changing_derivatives.md +1 -1
  6. data/doc/changing_location.md +8 -6
  7. data/doc/design.md +5 -5
  8. data/doc/direct_s3.md +25 -0
  9. data/doc/external/articles.md +16 -16
  10. data/doc/external/extensions.md +1 -1
  11. data/doc/getting_started.md +79 -27
  12. data/doc/metadata.md +1 -1
  13. data/doc/multiple_files.md +57 -22
  14. data/doc/paperclip.md +1 -0
  15. data/doc/plugins/backgrounding.md +4 -4
  16. data/doc/plugins/derivation_endpoint.md +24 -0
  17. data/doc/plugins/derivatives.md +11 -1
  18. data/doc/plugins/entity.md +12 -4
  19. data/doc/plugins/instrumentation.md +1 -1
  20. data/doc/plugins/keep_files.md +6 -4
  21. data/doc/plugins/model.md +8 -3
  22. data/doc/plugins/sequel.md +1 -1
  23. data/doc/plugins/validation_helpers.md +1 -1
  24. data/doc/processing.md +3 -2
  25. data/doc/refile.md +3 -3
  26. data/doc/release_notes/2.1.0.md +1 -1
  27. data/doc/release_notes/3.4.0.md +35 -0
  28. data/doc/release_notes/3.5.0.md +63 -0
  29. data/doc/retrieving_uploads.md +1 -1
  30. data/doc/testing.md +55 -17
  31. data/doc/upgrading_to_3.md +6 -8
  32. data/lib/shrine/plugins/activerecord.rb +3 -3
  33. data/lib/shrine/plugins/derivation_endpoint.rb +31 -30
  34. data/lib/shrine/plugins/derivatives.rb +25 -19
  35. data/lib/shrine/plugins/determine_mime_type.rb +2 -0
  36. data/lib/shrine/plugins/download_endpoint.rb +7 -0
  37. data/lib/shrine/plugins/entity.rb +14 -7
  38. data/lib/shrine/plugins/infer_extension.rb +4 -0
  39. data/lib/shrine/plugins/instrumentation.rb +17 -19
  40. data/lib/shrine/plugins/model.rb +3 -1
  41. data/lib/shrine/plugins/remove_attachment.rb +2 -0
  42. data/lib/shrine/plugins/sequel.rb +1 -1
  43. data/lib/shrine/plugins/validation_helpers.rb +1 -1
  44. data/lib/shrine/storage/s3.rb +17 -7
  45. data/lib/shrine/uploaded_file.rb +3 -2
  46. data/lib/shrine/version.rb +1 -1
  47. data/lib/shrine.rb +3 -3
  48. data/shrine.gemspec +3 -2
  49. metadata +26 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8cfa59ed1f6143ee9298ede17eeda07dba85f0f9c3309a5b7a9e7f6c41399f29
4
- data.tar.gz: 67a64a3a4f40c34797ca04279af73829acf4071eb118f78addefdbaa15e048da
3
+ metadata.gz: 46e9fa07aa69797777e3072eed12a4b901b357ae840c71f4facd5b0be2d79929
4
+ data.tar.gz: 0714e663dd130b9af96b195e5a3d87c128a0e6dd0b0598a7b2d4286e97223008
5
5
  SHA512:
6
- metadata.gz: e87a3dbb80a304f8af559b9c3d4e8badf8e47e4377afd74fe08d570042d65358d44878c4a0366fa3cded98fe166083275e86c61f3b51d28d35e070e0233dea35
7
- data.tar.gz: 83c93e76bf5513ab317ccabbdda86ce90f760e7b898dc9f40036af3e7ec915f48e55bd6f8efcf8661dacea672ce6b24b450db217815b062881169c8c90fd0cd3
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 | 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
- | Help & Discussion | [discourse.shrinerb.com](https://discourse.shrinerb.com) |
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
- Add the gem to your Gemfile:
33
+ Run:
33
34
 
34
- ```rb
35
- # Gemfile
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. Backill metadata
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
  ```
@@ -212,7 +212,7 @@ Photo.find_each do |photo|
212
212
  next unless attacher.stored?
213
213
 
214
214
  square = attacher.file.download do |original|
215
- ImageProcessor::MiniMagick
215
+ ImageProcessing::MiniMagick
216
216
  .source(original)
217
217
  .resize_to_fill!(150, 150)
218
218
  end
@@ -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 # persist changes if attachment has not changed in the meantime
62
- old_attacher.destroy_attached # delete files on old location
63
- rescue Shrine::AttachmentChanged, # attachment has changed during reuploading
64
- ActiveRecord::RecordNotFound # record has been deleted during reuploading
65
- attacher.destroy_attached # delete now orphaned files
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.
@@ -4,22 +4,22 @@ title: Articles
4
4
 
5
5
  ## Official articles
6
6
 
7
- | Article | Published |
8
- | :------- | --------: |
9
- | [Better File Uploads with Shrine: Eager Processing](https://twin.github.io/better-file-uploads-with-shrine-eager-processing) | 12&nbsp;Dec&nbsp;2019 |
10
- | [Shrine 3.0 Released](https://twin.github.io/shrine-3-0-released/) | 14&nbsp;Oct&nbsp;2019 |
11
- | [Upcoming Features in Shrine 3.0](https://twin.github.io/upcoming-features-in-shrine-3-0/) | 29&nbsp;Aug&nbsp;2019 |
12
- | [Better File Uploads with Shrine: Direct Uploads](https://twin.github.io/better-file-uploads-with-shrine-direct-uploads/) | 08&nbsp;Jan&nbsp;2018 |
13
- | [Better File Uploads with Shrine: Metadata](https://twin.github.io/better-file-uploads-with-shrine-metadata/) | 07&nbsp;Nov&nbsp;2016 |
14
- | [Better File Uploads with Shrine: Processing](https://twin.github.io/better-file-uploads-with-shrine-processing/) | 31&nbsp;Oct&nbsp;2016 |
15
- | [Better File Uploads with Shrine: Attachment](https://twin.github.io/better-file-uploads-with-shrine-attachment/) | 17&nbsp;Sep&nbsp;2016 |
16
- | [Better File Uploads with Shrine: Uploader](https://twin.github.io/better-file-uploads-with-shrine-uploader/) | 16&nbsp;Sep&nbsp;2016 |
17
- | [Better File Uploads with Shrine: Motivation](https://twin.github.io/better-file-uploads-with-shrine-motivation/) | 11&nbsp;Sep&nbsp;2016 |
18
- | [Resumable File Uploads in Ruby](https://twin.github.io/resumable-file-uploads-in-ruby/) | 04&nbsp;Sep&nbsp;2016 |
19
- | [Shrine meets Transloadit](https://twin.github.io/shrine-meets-transloadit/) | 11&nbsp;Jul&nbsp;2016 |
20
- | [Shrine 2.0 Released](https://twin.github.io/shrine-2-0-released/) | 20&nbsp;May&nbsp;2016 |
21
- | [Asynchronous File Uploads](http://twin.github.io/file-uploads-asynchronous-world) | 18&nbsp;Jan&nbsp;2016 |
22
- | [Introducing Shrine](http://twin.github.io/introducing-shrine) | 04&nbsp;Oct&nbsp;2015 |
7
+ | Article | Published |
8
+ | :------- | --------: |
9
+ | [Better File Uploads with Shrine: Eager Processing](https://janko.io/better-file-uploads-with-shrine-eager-processing/) | 12&nbsp;Dec&nbsp;2019 |
10
+ | [Shrine 3.0 Released](https://janko.io/shrine-3-0-released/) | 14&nbsp;Oct&nbsp;2019 |
11
+ | [Upcoming Features in Shrine 3.0](https://janko.io/upcoming-features-in-shrine-3-0/) | 29&nbsp;Aug&nbsp;2019 |
12
+ | [Better File Uploads with Shrine: Direct Uploads](https://janko.io/better-file-uploads-with-shrine-direct-uploads/) | 08&nbsp;Jan&nbsp;2018 |
13
+ | [Better File Uploads with Shrine: Metadata](https://janko.io/better-file-uploads-with-shrine-metadata/) | 07&nbsp;Nov&nbsp;2016 |
14
+ | [Better File Uploads with Shrine: Processing](https://janko.io/better-file-uploads-with-shrine-processing/) | 31&nbsp;Oct&nbsp;2016 |
15
+ | [Better File Uploads with Shrine: Attachment](https://janko.io/better-file-uploads-with-shrine-attachment/) | 17&nbsp;Sep&nbsp;2016 |
16
+ | [Better File Uploads with Shrine: Uploader](https://janko.io/better-file-uploads-with-shrine-uploader/) | 16&nbsp;Sep&nbsp;2016 |
17
+ | [Better File Uploads with Shrine: Motivation](https://janko.io/better-file-uploads-with-shrine-motivation/) | 11&nbsp;Sep&nbsp;2016 |
18
+ | [Resumable File Uploads in Ruby](https://janko.io/resumable-file-uploads-in-ruby/) | 04&nbsp;Sep&nbsp;2016 |
19
+ | [Shrine meets Transloadit](https://janko.io/shrine-meets-transloadit/) | 11&nbsp;Jul&nbsp;2016 |
20
+ | [Shrine 2.0 Released](https://janko.io/shrine-2-0-released/) | 20&nbsp;May&nbsp;2016 |
21
+ | [Asynchronous File Uploads](http://janko.io/file-uploads-asynchronous-world) | 18&nbsp;Jan&nbsp;2016 |
22
+ | [Introducing Shrine](http://janko.io/introducing-shrine) | 04&nbsp;Oct&nbsp;2015 |
23
23
 
24
24
  ## Community articles
25
25
 
@@ -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) | Plugin for [AWS Lambda](https://aws.amazon.com/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/) |
@@ -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
- <!--DOCUSAURUS_CODE_TABS-->
36
- <!--Sequel-->
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
- <!--ActiveRecord-->
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
- <!--Rails-->
53
- ```
54
- $ rails generate migration add_image_data_to_photos image_data:text
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
- <!--END_DOCUSAURUS_CODE_TABS-->
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
- <!--DOCUSAURUS_CODE_TABS-->
69
- <!--Sequel-->
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
- <!--ActiveRecord-->
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
- <!--END_DOCUSAURUS_CODE_TABS-->
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
- <!--DOCUSAURUS_CODE_TABS-->
89
- <!--Rails form builder-->
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
- <!--Simple Form-->
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
- <!--Forme-->
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
- <!--HTML-->
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
- <!--END_DOCUSAURUS_CODE_TABS-->
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
- <!--DOCUSAURUS_CODE_TABS-->
133
- <!--Rails-->
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
- <!--Sinatra-->
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
- <!--END_DOCUSAURUS_CODE_TABS-->
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
- <!--DOCUSAURUS_CODE_TABS-->
161
- <!--Rails-->
199
+ <Tabs>
200
+ <TabItem value="rails" label="Rails">
201
+
162
202
  ```erb
163
203
  <%= image_tag @photo.image_url %>
164
204
  ```
165
- <!--HTML-->
205
+
206
+ </TabItem>
207
+ <TabItem value="html" label="HTML">
208
+
166
209
  ```erb
167
210
  <img src="<%= @photo.image_url %>" />
168
211
  ```
169
- <!--END_DOCUSAURUS_CODE_TABS-->
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 of thumbnails when the image is attached to a record, or you
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
data/doc/metadata.md CHANGED
@@ -175,7 +175,7 @@ uploaded_file.exif #=> {...}
175
175
  ```
176
176
 
177
177
  Or, if you're uploading videos, you might want to extract some video-specific
178
- meatadata:
178
+ metadata:
179
179
 
180
180
  ```rb
181
181
  # Gemfile