activestorage 7.0.8.1 → 7.2.2.1

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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +49 -360
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +6 -6
  5. data/app/assets/javascripts/activestorage.esm.js +11 -7
  6. data/app/assets/javascripts/activestorage.js +12 -6
  7. data/app/controllers/active_storage/disk_controller.rb +4 -2
  8. data/app/controllers/active_storage/representations/proxy_controller.rb +1 -1
  9. data/app/controllers/concerns/active_storage/file_server.rb +4 -1
  10. data/app/javascript/activestorage/blob_record.js +4 -1
  11. data/app/javascript/activestorage/direct_upload.js +3 -2
  12. data/app/javascript/activestorage/index.js +3 -1
  13. data/app/javascript/activestorage/ujs.js +3 -3
  14. data/app/jobs/active_storage/analyze_job.rb +1 -1
  15. data/app/jobs/active_storage/mirror_job.rb +1 -1
  16. data/app/jobs/active_storage/preview_image_job.rb +16 -0
  17. data/app/jobs/active_storage/purge_job.rb +1 -1
  18. data/app/jobs/active_storage/transform_job.rb +12 -0
  19. data/app/models/active_storage/attachment.rb +101 -16
  20. data/app/models/active_storage/blob/analyzable.rb +4 -3
  21. data/app/models/active_storage/blob/identifiable.rb +1 -0
  22. data/app/models/active_storage/blob/representable.rb +15 -3
  23. data/app/models/active_storage/blob/servable.rb +22 -0
  24. data/app/models/active_storage/blob.rb +59 -72
  25. data/app/models/active_storage/current.rb +0 -10
  26. data/app/models/active_storage/filename.rb +2 -4
  27. data/app/models/active_storage/named_variant.rb +21 -0
  28. data/app/models/active_storage/preview.rb +23 -8
  29. data/app/models/active_storage/variant.rb +10 -7
  30. data/app/models/active_storage/variant_record.rb +0 -2
  31. data/app/models/active_storage/variant_with_record.rb +21 -7
  32. data/app/models/active_storage/variation.rb +5 -3
  33. data/config/routes.rb +6 -4
  34. data/db/migrate/20170806125915_create_active_storage_tables.rb +2 -2
  35. data/lib/active_storage/analyzer/audio_analyzer.rb +16 -4
  36. data/lib/active_storage/analyzer/image_analyzer/vips.rb +5 -9
  37. data/lib/active_storage/analyzer/image_analyzer.rb +2 -0
  38. data/lib/active_storage/analyzer/video_analyzer.rb +9 -3
  39. data/lib/active_storage/analyzer.rb +2 -0
  40. data/lib/active_storage/attached/changes/create_many.rb +8 -3
  41. data/lib/active_storage/attached/changes/create_one.rb +51 -4
  42. data/lib/active_storage/attached/changes/create_one_of_many.rb +5 -1
  43. data/lib/active_storage/attached/many.rb +5 -4
  44. data/lib/active_storage/attached/model.rb +96 -60
  45. data/lib/active_storage/attached/one.rb +5 -4
  46. data/lib/active_storage/attached.rb +2 -0
  47. data/lib/active_storage/deprecator.rb +7 -0
  48. data/lib/active_storage/engine.rb +7 -9
  49. data/lib/active_storage/fixture_set.rb +7 -1
  50. data/lib/active_storage/gem_version.rb +3 -3
  51. data/lib/active_storage/log_subscriber.rb +12 -0
  52. data/lib/active_storage/previewer/mupdf_previewer.rb +6 -2
  53. data/lib/active_storage/previewer/poppler_pdf_previewer.rb +6 -2
  54. data/lib/active_storage/previewer/video_previewer.rb +1 -1
  55. data/lib/active_storage/previewer.rb +8 -1
  56. data/lib/active_storage/reflection.rb +3 -3
  57. data/lib/active_storage/service/azure_storage_service.rb +2 -0
  58. data/lib/active_storage/service/disk_service.rb +2 -0
  59. data/lib/active_storage/service/gcs_service.rb +11 -20
  60. data/lib/active_storage/service/mirror_service.rb +10 -5
  61. data/lib/active_storage/service/s3_service.rb +2 -0
  62. data/lib/active_storage/service.rb +4 -2
  63. data/lib/active_storage/transformers/image_processing_transformer.rb +1 -1
  64. data/lib/active_storage/transformers/transformer.rb +2 -0
  65. data/lib/active_storage/version.rb +1 -1
  66. data/lib/active_storage.rb +5 -4
  67. metadata +23 -32
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c56e609f79f82fe5a2a9ccfebd3e695d741d2dce0b2a32cff2f1c4d2a3eab038
4
- data.tar.gz: 9f1aa7c41de488d6be28acb49af7636571b3d482b28b244b762cedb07c1d814a
3
+ metadata.gz: 19f4fa25c348a39b38b18a049dd123c5a0c6f80d70e05cdfc4790c7e0dbf96d1
4
+ data.tar.gz: 48ba490e74129a1495ed0b3249730bfeba7b12f916e787849e7cfa4f81235bf9
5
5
  SHA512:
6
- metadata.gz: 1826cabe8f8ebb1c72b82b39746b95ff10fb71fedbdfaf59c7adba445029c4062b69d13367d79d0b7521d7cc294d4bb4e97077470cc7f88a23aab7100b2ac3e9
7
- data.tar.gz: a8550c67c260bd2b0ad1c0b2178f867f81a41be32e6cd3f140226c68677e4170c583f8c276b79cecc1f65813f80f84283b822e96b75e2e5237251337d9f72720
6
+ metadata.gz: 6656a5f10b464e63d86f0e4fc60984735e522d56789f93ce4f0d6ec4684b0b7e6a449f14af01a92e5929b1a4854f283b0bf89b37fe67ecb5d8cc207430b81c71
7
+ data.tar.gz: a8fe146a25f52b241de32978f344a2303ad5221f05306a57776337194ba67aa2691c715790131056dec44dfe21cb26b7df1fe33fef5d09efba3ff5f226b83e58
data/CHANGELOG.md CHANGED
@@ -1,414 +1,103 @@
1
- ## Rails 7.0.8.1 (February 21, 2024) ##
2
-
3
- * Disables the session in `ActiveStorage::Blobs::ProxyController`
4
- and `ActiveStorage::Representations::ProxyController`
5
- in order to allow caching by default in some CDNs as CloudFlare
6
-
7
- Fixes #44136
8
-
9
- *Bruno Prieto*
10
-
11
- ## Rails 7.0.8 (September 09, 2023) ##
12
-
13
- * No changes.
14
-
15
-
16
- ## Rails 7.0.7.2 (August 22, 2023) ##
17
-
18
- * No changes.
19
-
20
-
21
- ## Rails 7.0.7.1 (August 22, 2023) ##
22
-
23
- * No changes.
24
-
25
-
26
- ## Rails 7.0.7 (August 09, 2023) ##
27
-
28
- * No changes.
29
-
30
-
31
- ## Rails 7.0.6 (June 29, 2023) ##
32
-
33
- * Fix retrieving rotation value from FFmpeg on version 5.0+.
34
-
35
- In FFmpeg version 5.0+ the rotation value has been removed from tags.
36
- Instead the value can be found in side_data_list. Along with
37
- this update it's possible to have values of -90, -270 to denote the video
38
- has been rotated.
39
-
40
- *Haroon Ahmed*
41
-
42
-
43
- ## Rails 7.0.5.1 (June 26, 2023) ##
44
-
45
- * No changes.
46
-
47
-
48
- ## Rails 7.0.5 (May 24, 2023) ##
49
-
50
- * No changes.
51
-
52
-
53
- ## Rails 7.0.4.3 (March 13, 2023) ##
54
-
55
- * No changes.
56
-
57
-
58
- ## Rails 7.0.4.2 (January 24, 2023) ##
59
-
60
- * No changes.
61
-
62
-
63
- ## Rails 7.0.4.1 (January 17, 2023) ##
64
-
65
- * No changes.
66
-
67
-
68
- ## Rails 7.0.4 (September 09, 2022) ##
69
-
70
- * Fixes proxy downloads of files over 5MiB
71
-
72
- Previously, trying to view and/or download files larger than 5mb stored in
73
- services like S3 via proxy mode could return corrupted files at around
74
- 5.2mb or cause random halts in the download. Now,
75
- `ActiveStorage::Blobs::ProxyController` correctly handles streaming these
76
- larger files from the service to the client without any issues.
77
-
78
- Fixes #44679
79
-
80
- *Felipe Raul*
81
-
82
- ## Rails 7.0.3.1 (July 12, 2022) ##
83
-
84
- * No changes.
85
-
86
-
87
- ## Rails 7.0.3 (May 09, 2022) ##
88
-
89
- * Don't stream responses in redirect mode
90
-
91
- Previously, both redirect mode and proxy mode streamed their
92
- responses which caused a new thread to be created, and could end
93
- up leaking connections in the connection pool. But since redirect
94
- mode doesn't actually send any data, it doesn't need to be
95
- streamed.
96
-
97
- *Luke Lau*
98
-
99
- ## Rails 7.0.2.4 (April 26, 2022) ##
100
-
101
- * No changes.
102
-
103
-
104
- ## Rails 7.0.2.3 (March 08, 2022) ##
105
-
106
- * Added image transformation validation via configurable allow-list.
107
-
108
- Variant now offers a configurable allow-list for
109
- transformation methods in addition to a configurable deny-list for arguments.
110
-
111
- [CVE-2022-21831]
112
-
113
-
114
- ## Rails 7.0.2.2 (February 11, 2022) ##
1
+ ## Rails 7.2.2.1 (December 10, 2024) ##
115
2
 
116
3
  * No changes.
117
4
 
118
- ## Rails 7.0.2.1 (February 11, 2022) ##
119
-
120
- * No changes.
121
-
122
-
123
- ## Rails 7.0.2 (February 08, 2022) ##
124
-
125
- * Revert the ability to pass `service_name` param to `DirectUploadsController` which was introduced
126
- in 7.0.0.
127
5
 
128
- That change caused a lot of problems to upgrade Rails applications so we decided to remove it
129
- while in work in a more backwards compatible implementation.
130
-
131
- *Gannon McGibbon*
132
-
133
- * Allow applications to opt out of precompiling Active Storage JavaScript assets.
134
-
135
- *jlestavel*
136
-
137
-
138
- ## Rails 7.0.1 (January 06, 2022) ##
6
+ ## Rails 7.2.2 (October 30, 2024) ##
139
7
 
140
8
  * No changes.
141
9
 
142
10
 
143
- ## Rails 7.0.0 (December 15, 2021) ##
144
-
145
- * Support transforming empty-ish `has_many_attached` value into `[]` (e.g. `[""]`).
146
-
147
- ```ruby
148
- @user.highlights = [""]
149
- @user.highlights # => []
150
- ```
151
-
152
- *Sean Doyle*
153
-
154
-
155
- ## Rails 7.0.0.rc3 (December 14, 2021) ##
11
+ ## Rails 7.2.1.2 (October 23, 2024) ##
156
12
 
157
13
  * No changes.
158
14
 
159
15
 
160
- ## Rails 7.0.0.rc2 (December 14, 2021) ##
16
+ ## Rails 7.2.1.1 (October 15, 2024) ##
161
17
 
162
18
  * No changes.
163
19
 
164
- ## Rails 7.0.0.rc1 (December 06, 2021) ##
165
-
166
- * `Add ActiveStorage::Blob.compose` to concatenate multiple blobs.
167
-
168
- *Gannon McGibbon*
169
-
170
- * Setting custom metadata on blobs are now persisted to remote storage.
171
-
172
- *joshuamsager*
173
-
174
- * Support direct uploads to multiple services.
175
-
176
- *Dmitry Tsepelev*
177
-
178
- * Invalid default content types are deprecated
179
-
180
- Blobs created with content_type `image/jpg`, `image/pjpeg`, `image/bmp`, `text/javascript` will now produce
181
- a deprecation warning, since these are not valid content types.
182
20
 
183
- These content types will be removed from the defaults in Rails 7.1.
184
-
185
- You can set `config.active_storage.silence_invalid_content_types_warning = true` to dismiss the warning.
186
-
187
- *Alex Ghiculescu*
188
-
189
- ## Rails 7.0.0.alpha2 (September 15, 2021) ##
21
+ ## Rails 7.2.1 (August 22, 2024) ##
190
22
 
191
23
  * No changes.
192
24
 
193
25
 
194
- ## Rails 7.0.0.alpha1 (September 15, 2021) ##
195
-
196
- * Emit Active Support instrumentation events from Active Storage analyzers.
197
-
198
- Fixes #42930
199
-
200
- *Shouichi Kamiya*
201
-
202
- * Add support for byte range requests
203
-
204
- *Tom Prats*
205
-
206
- * Attachments can be deleted after their association is no longer defined.
207
-
208
- Fixes #42514
209
-
210
- *Don Sisco*
211
-
212
- * Make `vips` the default variant processor for new apps.
213
-
214
- See the upgrade guide for instructions on converting from `mini_magick` to `vips`. `mini_magick` is
215
- not deprecated, existing apps can keep using it.
216
-
217
- *Breno Gazzola*
218
-
219
- * Deprecate `ActiveStorage::Current.host` in favor of `ActiveStorage::Current.url_options` which accepts
220
- a host, protocol and port.
221
-
222
- *Santiago Bartesaghi*
223
-
224
- * Allow using [IAM](https://cloud.google.com/storage/docs/access-control/signed-urls) when signing URLs with GCS.
225
-
226
- ```yaml
227
- gcs:
228
- service: GCS
229
- ...
230
- iam: true
231
- ```
26
+ ## Rails 7.2.0 (August 09, 2024) ##
232
27
 
233
- *RRethy*
28
+ * Remove deprecated `config.active_storage.silence_invalid_content_types_warning`.
234
29
 
235
- * OpenSSL constants are now used for Digest computations.
30
+ *Rafael Mendonça França*
236
31
 
237
- *Dirkjan Bussink*
32
+ * Remove deprecated `config.active_storage.replace_on_assign_to_many`.
238
33
 
239
- * Deprecate `config.active_storage.replace_on_assign_to_many`. Future versions of Rails
240
- will behave the same way as when the config is set to `true`.
34
+ *Rafael Mendonça França*
241
35
 
242
- *Santiago Bartesaghi*
36
+ * Add support for custom `key` in `ActiveStorage::Blob#compose`.
243
37
 
244
- * Remove deprecated methods: `build_after_upload`, `create_after_upload!` in favor of `create_and_upload!`,
245
- and `service_url` in favor of `url`.
38
+ *Elvin Efendiev*
246
39
 
247
- *Santiago Bartesaghi*
40
+ * Add `image/webp` to `config.active_storage.web_image_content_types` when `load_defaults "7.2"`
41
+ is set.
248
42
 
249
- * Add support of `strict_loading_by_default` to `ActiveStorage::Representations` controllers.
43
+ *Lewis Buckley*
250
44
 
251
- *Anton Topchii*, *Andrew White*
45
+ * Fix JSON-encoding of `ActiveStorage::Filename` instances.
252
46
 
253
- * Allow to detach an attachment when record is not persisted.
47
+ *Jonathan del Strother*
254
48
 
255
- *Jacopo Beschi*
49
+ * Fix N+1 query when fetching preview images for non-image assets.
256
50
 
257
- * Use libvips instead of ImageMagick to analyze images when `active_storage.variant_processor = vips`.
51
+ *Aaron Patterson & Justin Searls*
258
52
 
259
- *Breno Gazzola*
53
+ * Fix all Active Storage database related models to respect
54
+ `ActiveRecord::Base.table_name_prefix` configuration.
260
55
 
261
- * Add metadata value for presence of video channel in video blobs.
56
+ *Chedli Bourguiba*
262
57
 
263
- The `metadata` attribute of video blobs has a new boolean key named `video` that is set to
264
- `true` if the file has an video channel and `false` if it doesn't.
58
+ * Fix `ActiveStorage::Representations::ProxyController` not returning the proper
59
+ preview image variant for previewable files.
265
60
 
266
- *Breno Gazzola*
61
+ *Chedli Bourguiba*
267
62
 
268
- * Deprecate usage of `purge` and `purge_later` from the association extension.
63
+ * Fix `ActiveStorage::Representations::ProxyController` to proxy untracked
64
+ variants.
269
65
 
270
- *Jacopo Beschi*
66
+ *Chedli Bourguiba*
271
67
 
272
- * Passing extra parameters in `ActiveStorage::Blob#url` to S3 Client.
68
+ * When using the `preprocessed: true` option, avoid enqueuing transform jobs
69
+ for blobs that are not representable.
273
70
 
274
- This allows calls of `ActiveStorage::Blob#url` to have more interaction with
275
- the S3 Presigner, enabling, amongst other options, custom S3 domain URL
276
- Generation.
71
+ *Chedli Bourguiba*
277
72
 
278
- ```ruby
279
- blob = ActiveStorage::Blob.last
73
+ * Prevent `ActiveStorage::Blob#preview` to generate a variant if an empty variation is passed.
280
74
 
281
- blob.url # => https://<bucket-name>.s3.<region>.amazonaws.com/<key>
282
- blob.url(virtual_host: true) # => # => https://<bucket-name>/<key>
283
- ```
75
+ Calls to `#url`, `#key` or `#download` will now use the original preview
76
+ image instead of generating a variant with the exact same dimensions.
284
77
 
285
- *josegomezr*
78
+ *Chedli Bourguiba*
286
79
 
287
- * Allow setting a `Cache-Control` on files uploaded to GCS.
80
+ * Process preview image variant when calling `ActiveStorage::Preview#processed`.
288
81
 
289
- ```yaml
290
- gcs:
291
- service: GCS
292
- ...
293
- cache_control: "public, max-age=3600"
294
- ```
82
+ For example, `attached_pdf.preview(:thumb).processed` will now immediately
83
+ generate the full-sized preview image and the `:thumb` variant of it.
84
+ Previously, the `:thumb` variant would not be generated until a further call
85
+ to e.g. `processed.url`.
295
86
 
296
- *maleblond*
87
+ *Chedli Bourguiba* and *Jonathan Hefner*
297
88
 
298
- * The parameters sent to `ffmpeg` for generating a video preview image are now
299
- configurable under `config.active_storage.video_preview_arguments`.
300
-
301
- *Brendon Muir*
302
-
303
- * The ActiveStorage video previewer will now use scene change detection to generate
304
- better preview images (rather than the previous default of using the first frame
305
- of the video). This change requires FFmpeg v3.4+.
89
+ * Prevent `ActiveRecord::StrictLoadingViolationError` when strict loading is
90
+ enabled and the variant of an Active Storage preview has already been
91
+ processed (for example, by calling `ActiveStorage::Preview#url`).
306
92
 
307
93
  *Jonathan Hefner*
308
94
 
309
- * Add support for ActiveStorage expiring URLs.
310
-
311
- ```ruby
312
- rails_blob_path(user.avatar, disposition: "attachment", expires_in: 30.minutes)
313
-
314
- <%= image_tag rails_blob_path(user.avatar.variant(resize: "100x100"), expires_in: 30.minutes) %>
315
- ```
316
-
317
- If you want to set default expiration time for ActiveStorage URLs throughout your application, set `config.active_storage.urls_expire_in`.
318
-
319
- *aki77*
320
-
321
- * Allow to purge an attachment when record is not persisted for `has_many_attached`.
322
-
323
- *Jacopo Beschi*
324
-
325
- * Add `with_all_variant_records` method to eager load all variant records on an attachment at once.
326
- `with_attached_image` scope now eager loads variant records if using variant tracking.
327
-
328
- *Alex Ghiculescu*
329
-
330
- * Add metadata value for presence of audio channel in video blobs.
331
-
332
- The `metadata` attribute of video blobs has a new boolean key named `audio` that is set to
333
- `true` if the file has an audio channel and `false` if it doesn't.
334
-
335
- *Breno Gazzola*
336
-
337
- * Adds analyzer for audio files.
338
-
339
- *Breno Gazzola*
340
-
341
- * Respect Active Record's primary_key_type in Active Storage migrations.
342
-
343
- *fatkodima*
344
-
345
- * Allow `expires_in` for ActiveStorage signed ids.
346
-
347
- *aki77*
348
-
349
- * Allow to purge an attachment when record is not persisted for `has_one_attached`.
350
-
351
- *Jacopo Beschi*
352
-
353
- * Add a load hook called `active_storage_variant_record` (providing `ActiveStorage::VariantRecord`)
354
- to allow for overriding aspects of the `ActiveStorage::VariantRecord` class. This makes
355
- `ActiveStorage::VariantRecord` consistent with `ActiveStorage::Blob` and `ActiveStorage::Attachment`
356
- that already have load hooks.
357
-
358
- *Brendon Muir*
359
-
360
- * `ActiveStorage::PreviewError` is raised when a previewer is unable to generate a preview image.
361
-
362
- *Alex Robbin*
363
-
364
- * Add `ActiveStorage::Streaming` module that can be included in a controller to get access to `#send_blob_stream`,
365
- which wraps the new `ActionController::Base#send_stream` method to stream a blob from cloud storage:
366
-
367
- ```ruby
368
- class MyPublicBlobsController < ApplicationController
369
- include ActiveStorage::SetBlob, ActiveStorage::Streaming
370
-
371
- def show
372
- http_cache_forever(public: true) do
373
- send_blob_stream @blob, disposition: params[:disposition]
374
- end
375
- end
376
- end
377
- ```
378
-
379
- *DHH*
380
-
381
- * Add ability to use pre-defined variants.
382
-
383
- ```ruby
384
- class User < ActiveRecord::Base
385
- has_one_attached :avatar do |attachable|
386
- attachable.variant :thumb, resize: "100x100"
387
- attachable.variant :medium, resize: "300x300", monochrome: true
388
- end
389
- end
390
-
391
- class Gallery < ActiveRecord::Base
392
- has_many_attached :photos do |attachable|
393
- attachable.variant :thumb, resize: "100x100"
394
- attachable.variant :medium, resize: "300x300", monochrome: true
395
- end
396
- end
397
-
398
- <%= image_tag user.avatar.variant(:thumb) %>
399
- ```
400
-
401
- *fatkodima*
402
-
403
- * After setting `config.active_storage.resolve_model_to_route = :rails_storage_proxy`
404
- `rails_blob_path` and `rails_representation_path` will generate proxy URLs by default.
405
-
406
- *Ali Ismayilov*
95
+ * Fix `preprocessed: true` option for named variants of previewable files.
407
96
 
408
- * Declare `ActiveStorage::FixtureSet` and `ActiveStorage::FixtureSet.blob` to
409
- improve fixture integration.
97
+ *Nico Wenterodt*
410
98
 
411
- *Sean Doyle*
99
+ * Allow accepting `service` as a proc as well in `has_one_attached` and `has_many_attached`.
412
100
 
101
+ *Yogesh Khater*
413
102
 
414
- Please check [6-1-stable](https://github.com/rails/rails/blob/6-1-stable/activestorage/CHANGELOG.md) for previous changes.
103
+ Please check [7-1-stable](https://github.com/rails/rails/blob/7-1-stable/activestorage/CHANGELOG.md) for previous changes.
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2017-2022 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.
@@ -508,7 +508,7 @@ function toArray(value) {
508
508
  }
509
509
 
510
510
  class BlobRecord {
511
- constructor(file, checksum, url) {
511
+ constructor(file, checksum, url, customHeaders = {}) {
512
512
  this.file = file;
513
513
  this.attributes = {
514
514
  filename: file.name,
@@ -522,6 +522,9 @@ class BlobRecord {
522
522
  this.xhr.setRequestHeader("Content-Type", "application/json");
523
523
  this.xhr.setRequestHeader("Accept", "application/json");
524
524
  this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
525
+ Object.keys(customHeaders).forEach((headerKey => {
526
+ this.xhr.setRequestHeader(headerKey, customHeaders[headerKey]);
527
+ }));
525
528
  const csrfToken = getMetaValue("csrf-token");
526
529
  if (csrfToken != undefined) {
527
530
  this.xhr.setRequestHeader("X-CSRF-Token", csrfToken);
@@ -604,11 +607,12 @@ class BlobUpload {
604
607
  let id = 0;
605
608
 
606
609
  class DirectUpload {
607
- constructor(file, url, delegate) {
610
+ constructor(file, url, delegate, customHeaders = {}) {
608
611
  this.id = ++id;
609
612
  this.file = file;
610
613
  this.url = url;
611
614
  this.delegate = delegate;
615
+ this.customHeaders = customHeaders;
612
616
  }
613
617
  create(callback) {
614
618
  FileChecksum.create(this.file, ((error, checksum) => {
@@ -616,7 +620,7 @@ class DirectUpload {
616
620
  callback(error);
617
621
  return;
618
622
  }
619
- const blob = new BlobRecord(this.file, checksum, this.url);
623
+ const blob = new BlobRecord(this.file, checksum, this.url, this.customHeaders);
620
624
  notify(this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr);
621
625
  blob.create((error => {
622
626
  if (error) {
@@ -767,9 +771,9 @@ function start() {
767
771
  }
768
772
 
769
773
  function didClick(event) {
770
- const {target: target} = event;
771
- if ((target.tagName == "INPUT" || target.tagName == "BUTTON") && target.type == "submit" && target.form) {
772
- submitButtonsByForm.set(target.form, target);
774
+ const button = event.target.closest("button, input");
775
+ if (button && button.type === "submit" && button.form) {
776
+ submitButtonsByForm.set(button.form, button);
773
777
  }
774
778
  }
775
779
 
@@ -841,4 +845,4 @@ function autostart() {
841
845
 
842
846
  setTimeout(autostart, 1);
843
847
 
844
- export { DirectUpload, start };
848
+ export { DirectUpload, DirectUploadController, DirectUploadsController, start };
@@ -503,7 +503,7 @@
503
503
  }
504
504
  }
505
505
  class BlobRecord {
506
- constructor(file, checksum, url) {
506
+ constructor(file, checksum, url, customHeaders = {}) {
507
507
  this.file = file;
508
508
  this.attributes = {
509
509
  filename: file.name,
@@ -517,6 +517,9 @@
517
517
  this.xhr.setRequestHeader("Content-Type", "application/json");
518
518
  this.xhr.setRequestHeader("Accept", "application/json");
519
519
  this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
520
+ Object.keys(customHeaders).forEach((headerKey => {
521
+ this.xhr.setRequestHeader(headerKey, customHeaders[headerKey]);
522
+ }));
520
523
  const csrfToken = getMetaValue("csrf-token");
521
524
  if (csrfToken != undefined) {
522
525
  this.xhr.setRequestHeader("X-CSRF-Token", csrfToken);
@@ -596,11 +599,12 @@
596
599
  }
597
600
  let id = 0;
598
601
  class DirectUpload {
599
- constructor(file, url, delegate) {
602
+ constructor(file, url, delegate, customHeaders = {}) {
600
603
  this.id = ++id;
601
604
  this.file = file;
602
605
  this.url = url;
603
606
  this.delegate = delegate;
607
+ this.customHeaders = customHeaders;
604
608
  }
605
609
  create(callback) {
606
610
  FileChecksum.create(this.file, ((error, checksum) => {
@@ -608,7 +612,7 @@
608
612
  callback(error);
609
613
  return;
610
614
  }
611
- const blob = new BlobRecord(this.file, checksum, this.url);
615
+ const blob = new BlobRecord(this.file, checksum, this.url, this.customHeaders);
612
616
  notify(this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr);
613
617
  blob.create((error => {
614
618
  if (error) {
@@ -750,9 +754,9 @@
750
754
  }
751
755
  }
752
756
  function didClick(event) {
753
- const {target: target} = event;
754
- if ((target.tagName == "INPUT" || target.tagName == "BUTTON") && target.type == "submit" && target.form) {
755
- submitButtonsByForm.set(target.form, target);
757
+ const button = event.target.closest("button, input");
758
+ if (button && button.type === "submit" && button.form) {
759
+ submitButtonsByForm.set(button.form, button);
756
760
  }
757
761
  }
758
762
  function didSubmitForm(event) {
@@ -816,6 +820,8 @@
816
820
  }
817
821
  setTimeout(autostart, 1);
818
822
  exports.DirectUpload = DirectUpload;
823
+ exports.DirectUploadController = DirectUploadController;
824
+ exports.DirectUploadsController = DirectUploadsController;
819
825
  exports.start = start;
820
826
  Object.defineProperty(exports, "__esModule", {
821
827
  value: true
@@ -42,11 +42,13 @@ class ActiveStorage::DiskController < ActiveStorage::BaseController
42
42
  end
43
43
 
44
44
  def decode_verified_key
45
- ActiveStorage.verifier.verified(params[:encoded_key], purpose: :blob_key)
45
+ key = ActiveStorage.verifier.verified(params[:encoded_key], purpose: :blob_key)
46
+ key&.deep_symbolize_keys
46
47
  end
47
48
 
48
49
  def decode_verified_token
49
- ActiveStorage.verifier.verified(params[:encoded_token], purpose: :blob_token)
50
+ token = ActiveStorage.verifier.verified(params[:encoded_token], purpose: :blob_token)
51
+ token&.deep_symbolize_keys
50
52
  end
51
53
 
52
54
  def acceptable_content?(token)
@@ -12,7 +12,7 @@ class ActiveStorage::Representations::ProxyController < ActiveStorage::Represent
12
12
 
13
13
  def show
14
14
  http_cache_forever public: true do
15
- send_blob_stream @representation.image, disposition: params[:disposition]
15
+ send_blob_stream @representation, disposition: params[:disposition]
16
16
  end
17
17
  end
18
18
  end