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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +158 -178
- data/MIT-LICENSE +1 -1
- data/README.md +7 -7
- data/app/assets/javascripts/activestorage.esm.js +10 -18
- data/app/assets/javascripts/activestorage.js +11 -17
- data/app/controllers/active_storage/base_controller.rb +1 -1
- data/app/controllers/active_storage/blobs/proxy_controller.rb +2 -0
- data/app/controllers/active_storage/direct_uploads_controller.rb +1 -7
- data/app/controllers/active_storage/disk_controller.rb +4 -2
- data/app/controllers/active_storage/representations/proxy_controller.rb +3 -0
- data/app/controllers/concerns/active_storage/disable_session.rb +12 -0
- data/app/controllers/concerns/active_storage/file_server.rb +4 -1
- data/app/controllers/concerns/active_storage/streaming.rb +1 -0
- data/app/javascript/activestorage/blob_record.js +6 -10
- data/app/javascript/activestorage/direct_upload.js +3 -4
- data/app/javascript/activestorage/direct_upload_controller.js +1 -9
- data/app/javascript/activestorage/index.js +3 -1
- data/app/jobs/active_storage/analyze_job.rb +1 -1
- data/app/jobs/active_storage/mirror_job.rb +1 -1
- data/app/jobs/active_storage/purge_job.rb +1 -1
- data/app/jobs/active_storage/transform_job.rb +12 -0
- data/app/models/active_storage/attachment.rb +88 -14
- data/app/models/active_storage/blob/analyzable.rb +4 -3
- data/app/models/active_storage/blob/identifiable.rb +1 -0
- data/app/models/active_storage/blob/representable.rb +7 -3
- data/app/models/active_storage/blob.rb +27 -47
- data/app/models/active_storage/current.rb +0 -10
- data/app/models/active_storage/filename.rb +2 -0
- data/app/models/active_storage/named_variant.rb +21 -0
- data/app/models/active_storage/preview.rb +5 -3
- data/app/models/active_storage/variant.rb +11 -10
- data/app/models/active_storage/variant_with_record.rb +20 -8
- data/app/models/active_storage/variation.rb +6 -4
- data/config/routes.rb +6 -4
- data/db/migrate/20170806125915_create_active_storage_tables.rb +1 -1
- data/db/update_migrate/20190112182829_add_service_name_to_active_storage_blobs.rb +4 -0
- data/db/update_migrate/20191206030411_create_active_storage_variant_records.rb +2 -0
- data/db/update_migrate/20211119233751_remove_not_null_on_active_storage_blobs_checksum.rb +2 -0
- data/lib/active_storage/analyzer/audio_analyzer.rb +17 -5
- data/lib/active_storage/analyzer/image_analyzer/image_magick.rb +9 -7
- data/lib/active_storage/analyzer/image_analyzer/vips.rb +9 -7
- data/lib/active_storage/analyzer/image_analyzer.rb +2 -0
- data/lib/active_storage/analyzer/video_analyzer.rb +15 -6
- data/lib/active_storage/analyzer.rb +2 -0
- data/lib/active_storage/attached/changes/create_many.rb +8 -3
- data/lib/active_storage/attached/changes/create_one.rb +45 -3
- data/lib/active_storage/attached/many.rb +5 -4
- data/lib/active_storage/attached/model.rb +66 -43
- data/lib/active_storage/attached/one.rb +5 -4
- data/lib/active_storage/attached.rb +2 -0
- data/lib/active_storage/deprecator.rb +7 -0
- data/lib/active_storage/engine.rb +31 -9
- data/lib/active_storage/errors.rb +0 -3
- data/lib/active_storage/fixture_set.rb +7 -8
- data/lib/active_storage/gem_version.rb +2 -2
- data/lib/active_storage/log_subscriber.rb +12 -0
- data/lib/active_storage/previewer/video_previewer.rb +2 -0
- data/lib/active_storage/previewer.rb +8 -1
- data/lib/active_storage/reflection.rb +3 -3
- data/lib/active_storage/service/azure_storage_service.rb +2 -0
- data/lib/active_storage/service/disk_service.rb +2 -0
- data/lib/active_storage/service/gcs_service.rb +11 -20
- data/lib/active_storage/service/mirror_service.rb +10 -5
- data/lib/active_storage/service/s3_service.rb +2 -0
- data/lib/active_storage/service.rb +4 -2
- data/lib/active_storage/transformers/image_processing_transformer.rb +65 -0
- data/lib/active_storage/transformers/transformer.rb +2 -0
- data/lib/active_storage/version.rb +1 -1
- data/lib/active_storage.rb +310 -4
- metadata +21 -32
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3f09e751b9896e3e99bda5b07a2f946e14cc08a8b25b29b872c85d918fa906c1
|
4
|
+
data.tar.gz: f10ad7fbf13f79f91b690a6417a7f035038f62f2c82ee39a94070566773c2bd5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d5fc945abbfdfbe05b6aeafa393ef6b6995fa1c0e6f908006dc52e570ba9d17e982f40df652814b95e5da0db68a7bacf8f0a7820de2bec928fbaf1519fed00bd
|
7
|
+
data.tar.gz: 627a0bf0f41c633ce7f3c098b264ffafebe6d081b2aea39ef0c9e30985fe06fb167b192abfd5fd5d729cef9592abe2acade5760ea792089373482dce1183b867
|
data/CHANGELOG.md
CHANGED
@@ -1,272 +1,252 @@
|
|
1
|
-
## Rails 7.
|
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.
|
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
|
-
|
11
|
+
## Rails 7.1.0.rc1 (September 27, 2023) ##
|
27
12
|
|
28
|
-
*
|
13
|
+
* Add `expires_at` option to `ActiveStorage::Blob#signed_id`.
|
29
14
|
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
-
*
|
20
|
+
*Aki*
|
37
21
|
|
38
|
-
|
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
|
-
|
24
|
+
```ruby
|
25
|
+
User.create!(avatar: File.open("image.jpg"))
|
26
|
+
User.create!(avatar: file_fixture("image.jpg"))
|
27
|
+
```
|
42
28
|
|
43
|
-
|
29
|
+
*Dorian Marié*
|
44
30
|
|
45
|
-
*Alex Ghiculescu*
|
46
31
|
|
47
|
-
## Rails 7.
|
32
|
+
## Rails 7.1.0.beta1 (September 13, 2023) ##
|
48
33
|
|
49
|
-
*
|
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
|
-
|
40
|
+
*Bruno Prieto*
|
53
41
|
|
54
|
-
*
|
42
|
+
* Add `tags` to `ActiveStorage::Analyzer::AudioAnalyzer` output
|
55
43
|
|
56
|
-
|
44
|
+
*Keaton Roux*
|
57
45
|
|
58
|
-
|
46
|
+
* Add an option to preprocess variants
|
59
47
|
|
60
|
-
|
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
|
-
|
52
|
+
`preprocessed` option is added when declaring variants.
|
63
53
|
|
64
|
-
|
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
|
-
|
62
|
+
*Shouichi Kamiya*
|
67
63
|
|
68
|
-
|
64
|
+
* Fix variants not included when eager loading multiple records containing a single attachment
|
69
65
|
|
70
|
-
|
66
|
+
When using the `with_attached_#{name}` scope for a `has_one_attached` relation,
|
67
|
+
attachment variants were not eagerly loaded.
|
71
68
|
|
72
|
-
|
73
|
-
not deprecated, existing apps can keep using it.
|
69
|
+
*Russell Porter*
|
74
70
|
|
75
|
-
|
71
|
+
* Allow an ActiveStorage attachment to be removed via a form post
|
76
72
|
|
77
|
-
|
78
|
-
|
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
|
-
|
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
|
-
|
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
|
-
*
|
92
|
-
|
93
|
-
* OpenSSL constants are now used for Digest computations.
|
94
|
-
|
95
|
-
*Dirkjan Bussink*
|
88
|
+
*Nate Matykiewicz*
|
96
89
|
|
97
|
-
*
|
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
|
-
|
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
|
-
*
|
103
|
-
and `service_url` in favor of `url`.
|
95
|
+
*Vipul A M*
|
104
96
|
|
105
|
-
|
97
|
+
* Allow destroying active storage variants
|
106
98
|
|
107
|
-
|
99
|
+
```ruby
|
100
|
+
User.first.avatar.variant(resize_to_limit: [100, 100]).destroy
|
101
|
+
```
|
108
102
|
|
109
|
-
*
|
103
|
+
*Shouichi Kamiya*, *Yuichiro NAKAGAWA*, *Ryohei UEDA*
|
110
104
|
|
111
|
-
*
|
105
|
+
* Add `sample_rate` to `ActiveStorage::Analyzer::AudioAnalyzer` output
|
112
106
|
|
113
|
-
*
|
107
|
+
*Matija Čupić*
|
114
108
|
|
115
|
-
*
|
109
|
+
* Remove deprecated `purge` and `purge_later` methods from the attachments association.
|
116
110
|
|
117
|
-
*
|
111
|
+
*Rafael Mendonça França*
|
118
112
|
|
119
|
-
*
|
113
|
+
* Remove deprecated behavior when assigning to a collection of attachments.
|
120
114
|
|
121
|
-
|
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
|
-
*
|
117
|
+
*Rafael Mendonça França*
|
125
118
|
|
126
|
-
*
|
119
|
+
* Remove deprecated `ActiveStorage::Current#host` and `ActiveStorage::Current#host=` methods.
|
127
120
|
|
128
|
-
*
|
121
|
+
*Rafael Mendonça França*
|
129
122
|
|
130
|
-
*
|
123
|
+
* Remove deprecated invalid default content types in Active Storage configurations.
|
131
124
|
|
132
|
-
|
133
|
-
the S3 Presigner, enabling, amongst other options, custom S3 domain URL
|
134
|
-
Generation.
|
125
|
+
*Rafael Mendonça França*
|
135
126
|
|
136
|
-
|
137
|
-
blob = ActiveStorage::Blob.last
|
127
|
+
* Add missing preview event to `ActiveStorage::LogSubscriber`
|
138
128
|
|
139
|
-
|
140
|
-
|
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
|
-
|
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
|
-
*
|
136
|
+
*Chedli Bourguiba*
|
146
137
|
|
147
|
-
|
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
|
-
|
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
|
-
*
|
157
|
-
configurable under `config.active_storage.video_preview_arguments`.
|
145
|
+
*Haroon Ahmed*
|
158
146
|
|
159
|
-
|
147
|
+
* Touch all corresponding model records after ActiveStorage::Blob is analyzed
|
160
148
|
|
161
|
-
|
162
|
-
|
163
|
-
|
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
|
-
*
|
154
|
+
*Nate Matykiewicz*
|
166
155
|
|
167
|
-
* Add
|
156
|
+
* Add ability to use pre-defined variants when calling `preview` or
|
157
|
+
`representation` on an attachment.
|
168
158
|
|
169
159
|
```ruby
|
170
|
-
|
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
|
166
|
+
<%= image_tag user.file.representation(:thumb) %>
|
173
167
|
```
|
174
168
|
|
175
|
-
|
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
|
-
*
|
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
|
-
*
|
174
|
+
*Santiago Bartesaghi*
|
202
175
|
|
203
|
-
*
|
176
|
+
* Fixes multiple `attach` calls within transaction not uploading files correctly.
|
204
177
|
|
205
|
-
|
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
|
-
|
193
|
+
assert_equal 2, user.attachments.count
|
194
|
+
assert user.attachments.first.service.exist?(user.attachments.first.key) # Fails
|
195
|
+
```
|
208
196
|
|
209
|
-
|
197
|
+
This was addressed by keeping track of the subchanges pending upload, and uploading them
|
198
|
+
once the transaction is committed.
|
210
199
|
|
211
|
-
|
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
|
-
*
|
202
|
+
*Santiago Bartesaghi*, *Bruno Vezoli*, *Juan Roig*, *Abhay Nikam*
|
217
203
|
|
218
|
-
*
|
204
|
+
* Raise an exception if `config.active_storage.service` is not set.
|
219
205
|
|
220
|
-
|
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
|
-
*
|
223
|
-
which wraps the new `ActionController::Base#send_stream` method to stream a blob from cloud storage:
|
210
|
+
*Ghouse Mohamed*
|
224
211
|
|
225
|
-
|
226
|
-
class MyPublicBlobsController < ApplicationController
|
227
|
-
include ActiveStorage::SetBlob, ActiveStorage::Streaming
|
212
|
+
* Fixes proxy downloads of files over 5mb
|
228
213
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
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
|
-
|
220
|
+
Fixes #44679
|
238
221
|
|
239
|
-
*
|
222
|
+
*Felipe Raul*
|
240
223
|
|
241
|
-
|
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
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
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
|
-
|
257
|
-
```
|
232
|
+
*Ghouse Mohamed*
|
258
233
|
|
259
|
-
|
234
|
+
* Don't stream responses in redirect mode
|
260
235
|
|
261
|
-
|
262
|
-
|
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
|
-
*
|
242
|
+
*Luke Lau*
|
265
243
|
|
266
|
-
*
|
267
|
-
improve fixture integration.
|
244
|
+
* Safe for direct upload on Libraries or Frameworks
|
268
245
|
|
269
|
-
|
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 [
|
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
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://
|
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
|
148
|
-
```
|
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
|
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
|
-
```
|
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,
|
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,
|
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.
|
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
|
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 };
|