activestorage 7.0.0 → 7.1.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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +158 -178
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +7 -7
  5. data/app/assets/javascripts/activestorage.esm.js +10 -18
  6. data/app/assets/javascripts/activestorage.js +11 -17
  7. data/app/controllers/active_storage/base_controller.rb +1 -1
  8. data/app/controllers/active_storage/blobs/proxy_controller.rb +2 -0
  9. data/app/controllers/active_storage/direct_uploads_controller.rb +1 -7
  10. data/app/controllers/active_storage/disk_controller.rb +4 -2
  11. data/app/controllers/active_storage/representations/proxy_controller.rb +3 -0
  12. data/app/controllers/concerns/active_storage/disable_session.rb +12 -0
  13. data/app/controllers/concerns/active_storage/file_server.rb +4 -1
  14. data/app/controllers/concerns/active_storage/streaming.rb +1 -0
  15. data/app/javascript/activestorage/blob_record.js +6 -10
  16. data/app/javascript/activestorage/direct_upload.js +3 -4
  17. data/app/javascript/activestorage/direct_upload_controller.js +1 -9
  18. data/app/javascript/activestorage/index.js +3 -1
  19. data/app/jobs/active_storage/analyze_job.rb +1 -1
  20. data/app/jobs/active_storage/mirror_job.rb +1 -1
  21. data/app/jobs/active_storage/purge_job.rb +1 -1
  22. data/app/jobs/active_storage/transform_job.rb +12 -0
  23. data/app/models/active_storage/attachment.rb +88 -14
  24. data/app/models/active_storage/blob/analyzable.rb +4 -3
  25. data/app/models/active_storage/blob/identifiable.rb +1 -0
  26. data/app/models/active_storage/blob/representable.rb +7 -3
  27. data/app/models/active_storage/blob.rb +27 -47
  28. data/app/models/active_storage/current.rb +0 -10
  29. data/app/models/active_storage/filename.rb +2 -0
  30. data/app/models/active_storage/named_variant.rb +21 -0
  31. data/app/models/active_storage/preview.rb +5 -3
  32. data/app/models/active_storage/variant.rb +11 -10
  33. data/app/models/active_storage/variant_with_record.rb +20 -8
  34. data/app/models/active_storage/variation.rb +6 -4
  35. data/config/routes.rb +6 -4
  36. data/db/migrate/20170806125915_create_active_storage_tables.rb +1 -1
  37. data/db/update_migrate/20190112182829_add_service_name_to_active_storage_blobs.rb +4 -0
  38. data/db/update_migrate/20191206030411_create_active_storage_variant_records.rb +2 -0
  39. data/db/update_migrate/20211119233751_remove_not_null_on_active_storage_blobs_checksum.rb +2 -0
  40. data/lib/active_storage/analyzer/audio_analyzer.rb +17 -5
  41. data/lib/active_storage/analyzer/image_analyzer/image_magick.rb +9 -7
  42. data/lib/active_storage/analyzer/image_analyzer/vips.rb +9 -7
  43. data/lib/active_storage/analyzer/image_analyzer.rb +2 -0
  44. data/lib/active_storage/analyzer/video_analyzer.rb +15 -6
  45. data/lib/active_storage/analyzer.rb +2 -0
  46. data/lib/active_storage/attached/changes/create_many.rb +8 -3
  47. data/lib/active_storage/attached/changes/create_one.rb +45 -3
  48. data/lib/active_storage/attached/many.rb +5 -4
  49. data/lib/active_storage/attached/model.rb +66 -43
  50. data/lib/active_storage/attached/one.rb +5 -4
  51. data/lib/active_storage/attached.rb +2 -0
  52. data/lib/active_storage/deprecator.rb +7 -0
  53. data/lib/active_storage/engine.rb +31 -9
  54. data/lib/active_storage/errors.rb +0 -3
  55. data/lib/active_storage/fixture_set.rb +7 -8
  56. data/lib/active_storage/gem_version.rb +2 -2
  57. data/lib/active_storage/log_subscriber.rb +12 -0
  58. data/lib/active_storage/previewer/video_previewer.rb +2 -0
  59. data/lib/active_storage/previewer.rb +8 -1
  60. data/lib/active_storage/reflection.rb +3 -3
  61. data/lib/active_storage/service/azure_storage_service.rb +2 -0
  62. data/lib/active_storage/service/disk_service.rb +2 -0
  63. data/lib/active_storage/service/gcs_service.rb +11 -20
  64. data/lib/active_storage/service/mirror_service.rb +10 -5
  65. data/lib/active_storage/service/s3_service.rb +2 -0
  66. data/lib/active_storage/service.rb +4 -2
  67. data/lib/active_storage/transformers/image_processing_transformer.rb +65 -0
  68. data/lib/active_storage/transformers/transformer.rb +2 -0
  69. data/lib/active_storage/version.rb +1 -1
  70. data/lib/active_storage.rb +310 -4
  71. metadata +21 -32
  72. data/lib/active_storage/direct_upload_token.rb +0 -59
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 85a5cf62726ae4b98295bb1b62926f4f2fa15257babdb8d6251cff37c682c354
4
- data.tar.gz: 65f662b546c7f3e5eaf0775f065174f6d7162721578d763213eefd2875565a7b
3
+ metadata.gz: 3f09e751b9896e3e99bda5b07a2f946e14cc08a8b25b29b872c85d918fa906c1
4
+ data.tar.gz: f10ad7fbf13f79f91b690a6417a7f035038f62f2c82ee39a94070566773c2bd5
5
5
  SHA512:
6
- metadata.gz: 3ff136a959f672bb822be34f573209a3017744a8ba476e8f6e2ec3de11130b9fb1bf4e876ee2b0233b1a2bfa9acd66d211b2b9b329f533b9449fd8d084482ec6
7
- data.tar.gz: 1d38c4402a276a86847c492c1d373fab6ace21b6149e03426744561a1528307947f4353645b53db5bdf32cfa4776aa0c15cfd0591631bdc554be66b481f5d77e
6
+ metadata.gz: d5fc945abbfdfbe05b6aeafa393ef6b6995fa1c0e6f908006dc52e570ba9d17e982f40df652814b95e5da0db68a7bacf8f0a7820de2bec928fbaf1519fed00bd
7
+ data.tar.gz: 627a0bf0f41c633ce7f3c098b264ffafebe6d081b2aea39ef0c9e30985fe06fb167b192abfd5fd5d729cef9592abe2acade5760ea792089373482dce1183b867
data/CHANGELOG.md CHANGED
@@ -1,272 +1,252 @@
1
- ## Rails 7.0.0 (December 15, 2021) ##
2
-
3
- * Support transforming empty-ish `has_many_attached` value into `[]` (e.g. `[""]`).
4
-
5
- ```ruby
6
- @user.highlights = [""]
7
- @user.highlights # => []
8
- ```
9
-
10
- *Sean Doyle*
11
-
12
-
13
- ## Rails 7.0.0.rc3 (December 14, 2021) ##
1
+ ## Rails 7.1.0 (October 05, 2023) ##
14
2
 
15
3
  * No changes.
16
4
 
17
5
 
18
- ## Rails 7.0.0.rc2 (December 14, 2021) ##
6
+ ## Rails 7.1.0.rc2 (October 01, 2023) ##
19
7
 
20
8
  * No changes.
21
9
 
22
- ## Rails 7.0.0.rc1 (December 06, 2021) ##
23
-
24
- * `Add ActiveStorage::Blob.compose` to concatenate multiple blobs.
25
10
 
26
- *Gannon McGibbon*
11
+ ## Rails 7.1.0.rc1 (September 27, 2023) ##
27
12
 
28
- * Setting custom metadata on blobs are now persisted to remote storage.
13
+ * Add `expires_at` option to `ActiveStorage::Blob#signed_id`.
29
14
 
30
- *joshuamsager*
31
-
32
- * Support direct uploads to multiple services.
33
-
34
- *Dmitry Tsepelev*
15
+ ```ruby
16
+ rails_blob_path(user.avatar, disposition: "attachment", expires_at: 30.minutes.from_now)
17
+ <%= image_tag rails_blob_path(user.avatar.variant(resize: "100x100"), expires_at: 30.minutes.from_now) %>
18
+ ```
35
19
 
36
- * Invalid default content types are deprecated
20
+ *Aki*
37
21
 
38
- Blobs created with content_type `image/jpg`, `image/pjpeg`, `image/bmp`, `text/javascript` will now produce
39
- a deprecation warning, since these are not valid content types.
22
+ * Allow attaching File and Pathname when assigning attributes, e.g.
40
23
 
41
- These content types will be removed from the defaults in Rails 7.1.
24
+ ```ruby
25
+ User.create!(avatar: File.open("image.jpg"))
26
+ User.create!(avatar: file_fixture("image.jpg"))
27
+ ```
42
28
 
43
- You can set `config.active_storage.silence_invalid_content_types_warning = true` to dismiss the warning.
29
+ *Dorian Marié*
44
30
 
45
- *Alex Ghiculescu*
46
31
 
47
- ## Rails 7.0.0.alpha2 (September 15, 2021) ##
32
+ ## Rails 7.1.0.beta1 (September 13, 2023) ##
48
33
 
49
- * No changes.
34
+ * Disables the session in `ActiveStorage::Blobs::ProxyController`
35
+ and `ActiveStorage::Representations::ProxyController`
36
+ in order to allow caching by default in some CDNs as CloudFlare
50
37
 
38
+ Fixes #44136
51
39
 
52
- ## Rails 7.0.0.alpha1 (September 15, 2021) ##
40
+ *Bruno Prieto*
53
41
 
54
- * Emit Active Support instrumentation events from Active Storage analyzers.
42
+ * Add `tags` to `ActiveStorage::Analyzer::AudioAnalyzer` output
55
43
 
56
- Fixes #42930
44
+ *Keaton Roux*
57
45
 
58
- *Shouichi Kamiya*
46
+ * Add an option to preprocess variants
59
47
 
60
- * Add support for byte range requests
48
+ ActiveStorage variants are processed on the fly when they are needed but
49
+ sometimes we're sure that they are accessed and want to processed them
50
+ upfront.
61
51
 
62
- *Tom Prats*
52
+ `preprocessed` option is added when declaring variants.
63
53
 
64
- * Attachments can be deleted after their association is no longer defined.
54
+ ```
55
+ class User < ApplicationRecord
56
+ has_one_attached :avatar do |attachable|
57
+ attachable.variant :thumb, resize_to_limit: [100, 100], preprocessed: true
58
+ end
59
+ end
60
+ ```
65
61
 
66
- Fixes #42514
62
+ *Shouichi Kamiya*
67
63
 
68
- *Don Sisco*
64
+ * Fix variants not included when eager loading multiple records containing a single attachment
69
65
 
70
- * Make `vips` the default variant processor for new apps.
66
+ When using the `with_attached_#{name}` scope for a `has_one_attached` relation,
67
+ attachment variants were not eagerly loaded.
71
68
 
72
- See the upgrade guide for instructions on converting from `mini_magick` to `vips`. `mini_magick` is
73
- not deprecated, existing apps can keep using it.
69
+ *Russell Porter*
74
70
 
75
- *Breno Gazzola*
71
+ * Allow an ActiveStorage attachment to be removed via a form post
76
72
 
77
- * Deprecate `ActiveStorage::Current.host` in favor of `ActiveStorage::Current.url_options` which accepts
78
- a host, protocol and port.
73
+ Attachments can already be removed by updating the attachment to be nil such as:
74
+ ```ruby
75
+ User.find(params[:id]).update!(avatar: nil)
76
+ ```
79
77
 
80
- *Santiago Bartesaghi*
78
+ However, a form cannot post a nil param, it can only post an empty string. But, posting an
79
+ empty string would result in an `ActiveSupport::MessageVerifier::InvalidSignature: mismatched digest`
80
+ error being raised, because it's being treated as a signed blob id.
81
81
 
82
- * Allow using [IAM](https://cloud.google.com/storage/docs/access-control/signed-urls) when signing URLs with GCS.
82
+ Now, nil and an empty string are treated as a delete, which allows attachments to be removed via:
83
+ ```ruby
84
+ User.find(params[:id]).update!(params.require(:user).permit(:avatar))
83
85
 
84
- ```yaml
85
- gcs:
86
- service: GCS
87
- ...
88
- iam: true
89
86
  ```
90
87
 
91
- *RRethy*
92
-
93
- * OpenSSL constants are now used for Digest computations.
94
-
95
- *Dirkjan Bussink*
88
+ *Nate Matykiewicz*
96
89
 
97
- * Deprecate `config.active_storage.replace_on_assign_to_many`. Future versions of Rails
98
- will behave the same way as when the config is set to `true`.
90
+ * Remove mini_mime usage in favour of marcel.
99
91
 
100
- *Santiago Bartesaghi*
92
+ We have two libraries that are have similar usage. This change removes
93
+ dependency on mini_mime and makes use of similar methods from marcel.
101
94
 
102
- * Remove deprecated methods: `build_after_upload`, `create_after_upload!` in favor of `create_and_upload!`,
103
- and `service_url` in favor of `url`.
95
+ *Vipul A M*
104
96
 
105
- *Santiago Bartesaghi*
97
+ * Allow destroying active storage variants
106
98
 
107
- * Add support of `strict_loading_by_default` to `ActiveStorage::Representations` controllers.
99
+ ```ruby
100
+ User.first.avatar.variant(resize_to_limit: [100, 100]).destroy
101
+ ```
108
102
 
109
- *Anton Topchii*, *Andrew White*
103
+ *Shouichi Kamiya*, *Yuichiro NAKAGAWA*, *Ryohei UEDA*
110
104
 
111
- * Allow to detach an attachment when record is not persisted.
105
+ * Add `sample_rate` to `ActiveStorage::Analyzer::AudioAnalyzer` output
112
106
 
113
- *Jacopo Beschi*
107
+ *Matija Čupić*
114
108
 
115
- * Use libvips instead of ImageMagick to analyze images when `active_storage.variant_processor = vips`.
109
+ * Remove deprecated `purge` and `purge_later` methods from the attachments association.
116
110
 
117
- *Breno Gazzola*
111
+ *Rafael Mendonça França*
118
112
 
119
- * Add metadata value for presence of video channel in video blobs.
113
+ * Remove deprecated behavior when assigning to a collection of attachments.
120
114
 
121
- The `metadata` attribute of video blobs has a new boolean key named `video` that is set to
122
- `true` if the file has an video channel and `false` if it doesn't.
115
+ Instead of appending to the collection, the collection is now replaced.
123
116
 
124
- *Breno Gazzola*
117
+ *Rafael Mendonça França*
125
118
 
126
- * Deprecate usage of `purge` and `purge_later` from the association extension.
119
+ * Remove deprecated `ActiveStorage::Current#host` and `ActiveStorage::Current#host=` methods.
127
120
 
128
- *Jacopo Beschi*
121
+ *Rafael Mendonça França*
129
122
 
130
- * Passing extra parameters in `ActiveStorage::Blob#url` to S3 Client.
123
+ * Remove deprecated invalid default content types in Active Storage configurations.
131
124
 
132
- This allows calls of `ActiveStorage::Blob#url` to have more interaction with
133
- the S3 Presigner, enabling, amongst other options, custom S3 domain URL
134
- Generation.
125
+ *Rafael Mendonça França*
135
126
 
136
- ```ruby
137
- blob = ActiveStorage::Blob.last
127
+ * Add missing preview event to `ActiveStorage::LogSubscriber`
138
128
 
139
- blob.url # => https://<bucket-name>.s3.<region>.amazonaws.com/<key>
140
- blob.url(virtual_host: true) # => # => https://<bucket-name>/<key>
141
- ```
129
+ A `preview` event is being instrumented in `ActiveStorage::Previewer`.
130
+ However it was not added inside ActiveStorage's LogSubscriber class.
142
131
 
143
- *josegomezr*
132
+ This will allow to have logs for when a preview happens
133
+ in the same fashion as all other ActiveStorage events such as
134
+ `upload` and `download` inside `Rails.logger`.
144
135
 
145
- * Allow setting a `Cache-Control` on files uploaded to GCS.
136
+ *Chedli Bourguiba*
146
137
 
147
- ```yaml
148
- gcs:
149
- service: GCS
150
- ...
151
- cache_control: "public, max-age=3600"
152
- ```
138
+ * Fix retrieving rotation value from FFmpeg on version 5.0+.
153
139
 
154
- *maleblond*
140
+ In FFmpeg version 5.0+ the rotation value has been removed from tags.
141
+ Instead the value can be found in side_data_list. Along with
142
+ this update it's possible to have values of -90, -270 to denote the video
143
+ has been rotated.
155
144
 
156
- * The parameters sent to `ffmpeg` for generating a video preview image are now
157
- configurable under `config.active_storage.video_preview_arguments`.
145
+ *Haroon Ahmed*
158
146
 
159
- *Brendon Muir*
147
+ * Touch all corresponding model records after ActiveStorage::Blob is analyzed
160
148
 
161
- * The ActiveStorage video previewer will now use scene change detection to generate
162
- better preview images (rather than the previous default of using the first frame
163
- of the video). This change requires FFmpeg v3.4+.
149
+ This fixes a race condition where a record can be requested and have a cache entry built, before
150
+ the initial `analyze_later` completes, which will not be invalidated until something else
151
+ updates the record. This also invalidates cache entries when a blob is re-analyzed, which
152
+ is helpful if a bug is fixed in an analyzer or a new analyzer is added.
164
153
 
165
- *Jonathan Hefner*
154
+ *Nate Matykiewicz*
166
155
 
167
- * Add support for ActiveStorage expiring URLs.
156
+ * Add ability to use pre-defined variants when calling `preview` or
157
+ `representation` on an attachment.
168
158
 
169
159
  ```ruby
170
- rails_blob_path(user.avatar, disposition: "attachment", expires_in: 30.minutes)
160
+ class User < ActiveRecord::Base
161
+ has_one_attached :file do |attachable|
162
+ attachable.variant :thumb, resize_to_limit: [100, 100]
163
+ end
164
+ end
171
165
 
172
- <%= image_tag rails_blob_path(user.avatar.variant(resize: "100x100"), expires_in: 30.minutes) %>
166
+ <%= image_tag user.file.representation(:thumb) %>
173
167
  ```
174
168
 
175
- If you want to set default expiration time for ActiveStorage URLs throughout your application, set `config.active_storage.urls_expire_in`.
176
-
177
- *aki77*
178
-
179
- * Allow to purge an attachment when record is not persisted for `has_many_attached`.
180
-
181
- *Jacopo Beschi*
182
-
183
- * Add `with_all_variant_records` method to eager load all variant records on an attachment at once.
184
- `with_attached_image` scope now eager loads variant records if using variant tracking.
185
-
186
- *Alex Ghiculescu*
187
-
188
- * Add metadata value for presence of audio channel in video blobs.
189
-
190
- The `metadata` attribute of video blobs has a new boolean key named `audio` that is set to
191
- `true` if the file has an audio channel and `false` if it doesn't.
192
-
193
- *Breno Gazzola*
194
-
195
- * Adds analyzer for audio files.
196
-
197
- *Breno Gazzola*
169
+ *Richard Böhme*
198
170
 
199
- * Respect Active Record's primary_key_type in Active Storage migrations.
171
+ * Method `attach` always returns the attachments except when the record
172
+ is persisted, unchanged, and saving it fails, in which case it returns `nil`.
200
173
 
201
- *fatkodima*
174
+ *Santiago Bartesaghi*
202
175
 
203
- * Allow `expires_in` for ActiveStorage signed ids.
176
+ * Fixes multiple `attach` calls within transaction not uploading files correctly.
204
177
 
205
- *aki77*
178
+ In the following example, the code failed to upload all but the last file to the configured service.
179
+ ```ruby
180
+ ActiveRecord::Base.transaction do
181
+ user.attachments.attach({
182
+ content_type: "text/plain",
183
+ filename: "dummy.txt",
184
+ io: ::StringIO.new("dummy"),
185
+ })
186
+ user.attachments.attach({
187
+ content_type: "text/plain",
188
+ filename: "dummy2.txt",
189
+ io: ::StringIO.new("dummy2"),
190
+ })
191
+ end
206
192
 
207
- * Allow to purge an attachment when record is not persisted for `has_one_attached`.
193
+ assert_equal 2, user.attachments.count
194
+ assert user.attachments.first.service.exist?(user.attachments.first.key) # Fails
195
+ ```
208
196
 
209
- *Jacopo Beschi*
197
+ This was addressed by keeping track of the subchanges pending upload, and uploading them
198
+ once the transaction is committed.
210
199
 
211
- * Add a load hook called `active_storage_variant_record` (providing `ActiveStorage::VariantRecord`)
212
- to allow for overriding aspects of the `ActiveStorage::VariantRecord` class. This makes
213
- `ActiveStorage::VariantRecord` consistent with `ActiveStorage::Blob` and `ActiveStorage::Attachment`
214
- that already have load hooks.
200
+ Fixes #41661
215
201
 
216
- *Brendon Muir*
202
+ *Santiago Bartesaghi*, *Bruno Vezoli*, *Juan Roig*, *Abhay Nikam*
217
203
 
218
- * `ActiveStorage::PreviewError` is raised when a previewer is unable to generate a preview image.
204
+ * Raise an exception if `config.active_storage.service` is not set.
219
205
 
220
- *Alex Robbin*
206
+ If Active Storage is configured and `config.active_storage.service` is not
207
+ set in the respective environment's configuration file, then an exception
208
+ is raised with a meaningful message when attempting to use Active Storage.
221
209
 
222
- * Add `ActiveStorage::Streaming` module that can be included in a controller to get access to `#send_blob_stream`,
223
- which wraps the new `ActionController::Base#send_stream` method to stream a blob from cloud storage:
210
+ *Ghouse Mohamed*
224
211
 
225
- ```ruby
226
- class MyPublicBlobsController < ApplicationController
227
- include ActiveStorage::SetBlob, ActiveStorage::Streaming
212
+ * Fixes proxy downloads of files over 5mb
228
213
 
229
- def show
230
- http_cache_forever(public: true) do
231
- send_blob_stream @blob, disposition: params[:disposition]
232
- end
233
- end
234
- end
235
- ```
214
+ Previously, trying to view and/or download files larger than 5mb stored in
215
+ services like S3 via proxy mode could return corrupted files at around
216
+ 5.2mb or cause random halts in the download. Now,
217
+ `ActiveStorage::Blobs::ProxyController` correctly handles streaming these
218
+ larger files from the service to the client without any issues.
236
219
 
237
- *DHH*
220
+ Fixes #44679
238
221
 
239
- * Add ability to use pre-defined variants.
222
+ *Felipe Raul*
240
223
 
241
- ```ruby
242
- class User < ActiveRecord::Base
243
- has_one_attached :avatar do |attachable|
244
- attachable.variant :thumb, resize: "100x100"
245
- attachable.variant :medium, resize: "300x300", monochrome: true
246
- end
247
- end
224
+ * Saving attachment(s) to a record returns the blob/blobs object
248
225
 
249
- class Gallery < ActiveRecord::Base
250
- has_many_attached :photos do |attachable|
251
- attachable.variant :thumb, resize: "100x100"
252
- attachable.variant :medium, resize: "300x300", monochrome: true
253
- end
254
- end
226
+ Previously, saving attachments did not return the blob/blobs that
227
+ were attached. Now, saving attachments to a record with `#attach`
228
+ method returns the blob or array of blobs that were attached to
229
+ the record. If it fails to save the attachment(s), then it returns
230
+ `false`.
255
231
 
256
- <%= image_tag user.avatar.variant(:thumb) %>
257
- ```
232
+ *Ghouse Mohamed*
258
233
 
259
- *fatkodima*
234
+ * Don't stream responses in redirect mode
260
235
 
261
- * After setting `config.active_storage.resolve_model_to_route = :rails_storage_proxy`
262
- `rails_blob_path` and `rails_representation_path` will generate proxy URLs by default.
236
+ Previously, both redirect mode and proxy mode streamed their
237
+ responses which caused a new thread to be created, and could end
238
+ up leaking connections in the connection pool. But since redirect
239
+ mode doesn't actually send any data, it doesn't need to be
240
+ streamed.
263
241
 
264
- *Ali Ismayilov*
242
+ *Luke Lau*
265
243
 
266
- * Declare `ActiveStorage::FixtureSet` and `ActiveStorage::FixtureSet.blob` to
267
- improve fixture integration.
244
+ * Safe for direct upload on Libraries or Frameworks
268
245
 
269
- *Sean Doyle*
246
+ Enable the use of custom headers during direct uploads, which allows for
247
+ the inclusion of Authorization bearer tokens or other forms of authorization
248
+ tokens through headers.
270
249
 
250
+ *Radamés Roriz*
271
251
 
272
- Please check [6-1-stable](https://github.com/rails/rails/blob/6-1-stable/activestorage/CHANGELOG.md) for previous changes.
252
+ Please check [7-0-stable](https://github.com/rails/rails/blob/7-0-stable/activestorage/CHANGELOG.md) for previous changes.
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2017-2021 David Heinemeier Hansson, Basecamp
1
+ Copyright (c) David Heinemeier Hansson, 37signals LLC
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -6,11 +6,11 @@ Files can be uploaded from the server to the cloud or directly from the client t
6
6
 
7
7
  Image files can furthermore be transformed using on-demand variants for quality, aspect ratio, size, or any other [MiniMagick](https://github.com/minimagick/minimagick) or [Vips](https://www.rubydoc.info/gems/ruby-vips/Vips/Image) supported transformation.
8
8
 
9
- You can read more about Active Storage in the [Active Storage Overview](https://edgeguides.rubyonrails.org/active_storage_overview.html) guide.
9
+ You can read more about Active Storage in the [Active Storage Overview](https://guides.rubyonrails.org/active_storage_overview.html) guide.
10
10
 
11
11
  ## Compared to other storage solutions
12
12
 
13
- A key difference to how Active Storage works compared to other attachment solutions in Rails is through the use of built-in [Blob](https://github.com/rails/rails/blob/main/activestorage/app/models/active_storage/blob.rb) and [Attachment](https://github.com/rails/rails/blob/main/activestorage/app/models/active_storage/attachment.rb) models (backed by Active Record). This means existing application models do not need to be modified with additional columns to associate with files. Active Storage uses polymorphic associations via the `Attachment` join model, which then connects to the actual `Blob`.
13
+ A key difference to how Active Storage works compared to other attachment solutions in \Rails is through the use of built-in [Blob](https://github.com/rails/rails/blob/main/activestorage/app/models/active_storage/blob.rb) and [Attachment](https://github.com/rails/rails/blob/main/activestorage/app/models/active_storage/attachment.rb) models (backed by Active Record). This means existing application models do not need to be modified with additional columns to associate with files. Active Storage uses polymorphic associations via the `Attachment` join model, which then connects to the actual `Blob`.
14
14
 
15
15
  `Blob` models store attachment metadata (filename, content-type, etc.), and their identifier key in the storage service. Blob models do not store the actual binary data. They are intended to be immutable in spirit. One file, one blob. You can associate the same blob with multiple application models as well. And if you want to do transformations of a given `Blob`, the idea is that you'll simply create a new one, rather than attempt to mutate the existing one (though of course you can delete the previous version later if you don't need it).
16
16
 
@@ -144,11 +144,11 @@ Active Storage, with its included JavaScript library, supports uploading directl
144
144
 
145
145
  1. Include the Active Storage JavaScript in your application's JavaScript bundle or reference it directly.
146
146
 
147
- Requiring directly without bundling through the asset pipeline in the application html with autostart:
148
- ```html
147
+ Requiring directly without bundling through the asset pipeline in the application HTML with autostart:
148
+ ```erb
149
149
  <%= javascript_include_tag "activestorage" %>
150
150
  ```
151
- Requiring via importmap-rails without bundling through the asset pipeline in the application html without autostart as ESM:
151
+ Requiring via importmap-rails without bundling through the asset pipeline in the application HTML without autostart as ESM:
152
152
  ```ruby
153
153
  # config/importmap.rb
154
154
  pin "@rails/activestorage", to: "activestorage.esm.js"
@@ -170,7 +170,7 @@ Active Storage, with its included JavaScript library, supports uploading directl
170
170
  ```
171
171
  2. Annotate file inputs with the direct upload URL.
172
172
 
173
- ```ruby
173
+ ```erb
174
174
  <%= form.file_field :attachments, multiple: true, direct_upload: true %>
175
175
  ```
176
176
  3. That's it! Uploads begin upon form submission.
@@ -199,7 +199,7 @@ API documentation is at:
199
199
 
200
200
  * https://api.rubyonrails.org
201
201
 
202
- Bug reports for the Ruby on Rails project can be filed here:
202
+ Bug reports for the Ruby on \Rails project can be filed here:
203
203
 
204
204
  * https://github.com/rails/rails/issues
205
205
 
@@ -508,7 +508,7 @@ function toArray(value) {
508
508
  }
509
509
 
510
510
  class BlobRecord {
511
- constructor(file, checksum, url, directUploadToken, attachmentName) {
511
+ constructor(file, checksum, url, customHeaders = {}) {
512
512
  this.file = file;
513
513
  this.attributes = {
514
514
  filename: file.name,
@@ -516,14 +516,15 @@ class BlobRecord {
516
516
  byte_size: file.size,
517
517
  checksum: checksum
518
518
  };
519
- this.directUploadToken = directUploadToken;
520
- this.attachmentName = attachmentName;
521
519
  this.xhr = new XMLHttpRequest;
522
520
  this.xhr.open("POST", url, true);
523
521
  this.xhr.responseType = "json";
524
522
  this.xhr.setRequestHeader("Content-Type", "application/json");
525
523
  this.xhr.setRequestHeader("Accept", "application/json");
526
524
  this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
525
+ Object.keys(customHeaders).forEach((headerKey => {
526
+ this.xhr.setRequestHeader(headerKey, customHeaders[headerKey]);
527
+ }));
527
528
  const csrfToken = getMetaValue("csrf-token");
528
529
  if (csrfToken != undefined) {
529
530
  this.xhr.setRequestHeader("X-CSRF-Token", csrfToken);
@@ -545,9 +546,7 @@ class BlobRecord {
545
546
  create(callback) {
546
547
  this.callback = callback;
547
548
  this.xhr.send(JSON.stringify({
548
- blob: this.attributes,
549
- direct_upload_token: this.directUploadToken,
550
- attachment_name: this.attachmentName
549
+ blob: this.attributes
551
550
  }));
552
551
  }
553
552
  requestDidLoad(event) {
@@ -608,13 +607,12 @@ class BlobUpload {
608
607
  let id = 0;
609
608
 
610
609
  class DirectUpload {
611
- constructor(file, url, serviceName, attachmentName, delegate) {
610
+ constructor(file, url, delegate, customHeaders = {}) {
612
611
  this.id = ++id;
613
612
  this.file = file;
614
613
  this.url = url;
615
- this.serviceName = serviceName;
616
- this.attachmentName = attachmentName;
617
614
  this.delegate = delegate;
615
+ this.customHeaders = customHeaders;
618
616
  }
619
617
  create(callback) {
620
618
  FileChecksum.create(this.file, ((error, checksum) => {
@@ -622,7 +620,7 @@ class DirectUpload {
622
620
  callback(error);
623
621
  return;
624
622
  }
625
- const blob = new BlobRecord(this.file, checksum, this.url, this.serviceName, this.attachmentName);
623
+ const blob = new BlobRecord(this.file, checksum, this.url, this.customHeaders);
626
624
  notify(this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr);
627
625
  blob.create((error => {
628
626
  if (error) {
@@ -653,7 +651,7 @@ class DirectUploadController {
653
651
  constructor(input, file) {
654
652
  this.input = input;
655
653
  this.file = file;
656
- this.directUpload = new DirectUpload(this.file, this.url, this.directUploadToken, this.attachmentName, this);
654
+ this.directUpload = new DirectUpload(this.file, this.url, this);
657
655
  this.dispatch("initialize");
658
656
  }
659
657
  start(callback) {
@@ -684,12 +682,6 @@ class DirectUploadController {
684
682
  get url() {
685
683
  return this.input.getAttribute("data-direct-upload-url");
686
684
  }
687
- get directUploadToken() {
688
- return this.input.getAttribute("data-direct-upload-token");
689
- }
690
- get attachmentName() {
691
- return this.input.getAttribute("data-direct-upload-attachment-name");
692
- }
693
685
  dispatch(name, detail = {}) {
694
686
  detail.file = this.file;
695
687
  detail.id = this.directUpload.id;
@@ -853,4 +845,4 @@ function autostart() {
853
845
 
854
846
  setTimeout(autostart, 1);
855
847
 
856
- export { DirectUpload, start };
848
+ export { DirectUpload, DirectUploadController, DirectUploadsController, start };