activestorage 8.1.3.1 → 8.1.4
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 +66 -0
- data/app/controllers/active_storage/blobs/proxy_controller.rb +18 -4
- data/app/controllers/active_storage/blobs/redirect_controller.rb +20 -4
- data/app/controllers/active_storage/representations/proxy_controller.rb +18 -4
- data/app/controllers/active_storage/representations/redirect_controller.rb +21 -4
- data/app/models/active_storage/attachment.rb +7 -3
- data/app/models/active_storage/blob.rb +11 -11
- data/app/models/active_storage/variant.rb +1 -1
- data/lib/active_storage/attached/changes/create_many.rb +2 -1
- data/lib/active_storage/attached/changes/create_one.rb +2 -1
- data/lib/active_storage/attached/changes/delete_many.rb +2 -1
- data/lib/active_storage/attached/changes/delete_one.rb +2 -1
- data/lib/active_storage/attached/many.rb +4 -0
- data/lib/active_storage/attached/model.rb +13 -2
- data/lib/active_storage/attached/one.rb +6 -0
- data/lib/active_storage/engine.rb +10 -0
- data/lib/active_storage/gem_version.rb +2 -2
- data/lib/active_storage/previewer.rb +1 -1
- data/lib/active_storage/service/mirror_service.rb +5 -3
- data/lib/active_storage.rb +4 -0
- metadata +13 -13
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 363218fe84c4760d1243ee6f1325312eab52a4d1d7c33f512022e1a8ad4ed8a5
|
|
4
|
+
data.tar.gz: 603439dba3d29a9f57b433232954d85d9ec70905ab6114d10e370b2136283258
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5277345f853e82ae059c49bde6c2664f84516dfbd4da948e7a48b437da363682104b56fb895b75e7010f7201c5ced03106297c24bba67977a2567b045b2faa60
|
|
7
|
+
data.tar.gz: 27b8cbc33599414d28774b41d1d3891a1fb803e4316e217f24e47903f8a2d5e6f92fd7ffb2d50d9b02efddf26fa08ae6a199993dbbfc4cdad37aab813df1b906
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,69 @@
|
|
|
1
|
+
## Rails 8.1.4 (September 24, 2026) ##
|
|
2
|
+
|
|
3
|
+
* Warn instead of aborting boot when `image_processing` 2.x is installed without `ruby-vips`
|
|
4
|
+
or `mini_magick`.
|
|
5
|
+
|
|
6
|
+
Both gems became soft dependencies in `image_processing` 2.0, and the `LoadError` raised for
|
|
7
|
+
a missing one names that gem instead of `image_processing`. Active Storage did not recognize
|
|
8
|
+
the message, so it re-raised rather than logging its usual warning.
|
|
9
|
+
|
|
10
|
+
Fixes #58413.
|
|
11
|
+
|
|
12
|
+
*Janko Marohnić*
|
|
13
|
+
|
|
14
|
+
* Fix `MirrorService#mirror` losing blob metadata when copying to mirrors.
|
|
15
|
+
|
|
16
|
+
Mirrored copies on S3, Azure, and GCS were served as `application/octet-stream`
|
|
17
|
+
because `content_type`, `filename`, `disposition`, and `custom_metadata` were
|
|
18
|
+
dropped. Forward the blob's `service_metadata` to each mirror's upload.
|
|
19
|
+
|
|
20
|
+
Fixes #57270.
|
|
21
|
+
|
|
22
|
+
*Maksim Romanov* + *Andrii Furmanets*
|
|
23
|
+
|
|
24
|
+
* Prevent `ActiveStorage.touch_attachment_records = false` from crashing the attachment of a Blob.
|
|
25
|
+
|
|
26
|
+
When `ActiveStorage.touch_attachment_records` was set to `false`, attaching a existing Blob to a Record
|
|
27
|
+
would raise an error. This is now fixed.
|
|
28
|
+
|
|
29
|
+
*Edouard Chin*
|
|
30
|
+
|
|
31
|
+
* Fix `MirrorService#mirror` raising `ActiveStorage::IntegrityError` when
|
|
32
|
+
mirroring without a checksum (e.g., `track_variants: false`).
|
|
33
|
+
|
|
34
|
+
*Denis Savchuk*
|
|
35
|
+
|
|
36
|
+
* Preserve attachment changes when converting record to another class using STI.
|
|
37
|
+
|
|
38
|
+
*fatkodima*
|
|
39
|
+
|
|
40
|
+
* Correct unexpected behavior resulting from dependent: :purge when using
|
|
41
|
+
has_one_attached or has_many_attached. Fixes #36423.
|
|
42
|
+
|
|
43
|
+
*Mark Oveson*
|
|
44
|
+
|
|
45
|
+
* Define `as_json` on `ActiveStorage::Attached::One` and `ActiveStorage::Attached::Many`.
|
|
46
|
+
|
|
47
|
+
The proxies hold a back-reference to the owning record in `@record`. Without an explicit
|
|
48
|
+
`as_json`, the default `Object#as_json` fall back serialized `instance_values`, which made
|
|
49
|
+
`record.to_json` recurse infinitely whenever the attached name collided with a model
|
|
50
|
+
attribute (e.g. an `ignored_columns` column brought back by `select('*')`).
|
|
51
|
+
|
|
52
|
+
`Attached::One#as_json` now returns the attachment record's JSON when attached and `nil`
|
|
53
|
+
otherwise. `Attached::Many#as_json` returns the attachment records' JSON as an array.
|
|
54
|
+
|
|
55
|
+
*Renxiang Cai*
|
|
56
|
+
|
|
57
|
+
* Fix Rails hanging when generating video previews
|
|
58
|
+
|
|
59
|
+
When Rails runs in a background process group, ffmpeg's attempt to configure the terminal for
|
|
60
|
+
interactive input would send SIGTTOU to the Rails process, suspending it indefinitely.
|
|
61
|
+
|
|
62
|
+
Fixed by explicitly passing /dev/null to ffmpeg's stdin.
|
|
63
|
+
|
|
64
|
+
*Jonathan del Strother*
|
|
65
|
+
|
|
66
|
+
|
|
1
67
|
## Rails 8.1.3.1 (July 29, 2026) ##
|
|
2
68
|
|
|
3
69
|
* Disable libvips's unfuzzed image loaders and savers.
|
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
#
|
|
3
|
+
# Finds a blob by a +signed_id+ and proxies the file through the application.
|
|
4
|
+
# The blob is streamed from storage directly to the response. This avoids having
|
|
5
|
+
# a redirect and makes files easier to cache.
|
|
4
6
|
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
7
|
+
# The +signed_id+s make URLs hard to guess but permanent by design, allowing the URLs to be cached.
|
|
8
|
+
# The response sets the HTTP cache to public and allows browsers and proxies to cache it indefinitely.
|
|
9
|
+
#
|
|
10
|
+
# The URLs created for this controller are set to never expire by default.
|
|
11
|
+
# To make URLs expire, pass the +expires_in+ option when generating the URL:
|
|
12
|
+
#
|
|
13
|
+
# rails_storage_proxy_url(blob, expires_in: 1.minute)
|
|
14
|
+
#
|
|
15
|
+
# Or set the default for all Active Storage URLs:
|
|
16
|
+
#
|
|
17
|
+
# config.active_storage.urls_expire_in = 1.day
|
|
18
|
+
#
|
|
19
|
+
# WARNING: All Active Storage controllers are publicly accessible by default.
|
|
20
|
+
# Anyone who knows the URL can access the file, even if the rest of your application requires
|
|
21
|
+
# authentication. If your files require access control consider implementing
|
|
8
22
|
# {Authenticated Controllers}[https://guides.rubyonrails.org/active_storage_overview.html#authenticated-controllers].
|
|
9
23
|
class ActiveStorage::Blobs::ProxyController < ActiveStorage::BaseController
|
|
10
24
|
include ActiveStorage::SetBlob
|
|
@@ -1,10 +1,26 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
#
|
|
3
|
+
# Finds a blob by a +signed_id+ and redirects to a blob's expiring service URL.
|
|
4
4
|
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
5
|
+
# The +signed_id+s make URLs hard to guess but permanent by design, allowing the URLs to be cached.
|
|
6
|
+
#
|
|
7
|
+
# The URLs created for this controller are set to never expire by default.
|
|
8
|
+
# To make URLs expire, pass the +expires_in+ option when generating the URL:
|
|
9
|
+
#
|
|
10
|
+
# rails_storage_redirect_url(blob, expires_in: 1.minute)
|
|
11
|
+
#
|
|
12
|
+
# Or set the default for all Active Storage URLs:
|
|
13
|
+
#
|
|
14
|
+
# config.active_storage.urls_expire_in = 1.day
|
|
15
|
+
#
|
|
16
|
+
# The service URLs are set to expire in 5 minutes by default.
|
|
17
|
+
# The default can be changed for all service URLs:
|
|
18
|
+
#
|
|
19
|
+
# config.active_storage.service_urls_expire_in = 1.hour
|
|
20
|
+
#
|
|
21
|
+
# WARNING: All Active Storage controllers are publicly accessible by default.
|
|
22
|
+
# Anyone who knows the URL can access the file, even if the rest of your application requires
|
|
23
|
+
# authentication. If your files require access control consider implementing
|
|
8
24
|
# {Authenticated Controllers}[https://guides.rubyonrails.org/active_storage_overview.html#authenticated-controllers].
|
|
9
25
|
class ActiveStorage::Blobs::RedirectController < ActiveStorage::BaseController
|
|
10
26
|
include ActiveStorage::SetBlob
|
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
#
|
|
3
|
+
# Finds a representation by a +signed_id+ and a +variation_key+, and proxies the file through the application.
|
|
4
|
+
# The representation is streamed from storage directly to the response. This avoids having
|
|
5
|
+
# a redirect and makes files easier to cache.
|
|
4
6
|
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
7
|
+
# The +signed_id+s make URLs hard to guess but permanent by design, allowing the URLs to be cached.
|
|
8
|
+
# The response sets the HTTP cache to public and allows browsers and proxies to cache it indefinitely.
|
|
9
|
+
#
|
|
10
|
+
# The URLs created for this controller are set to never expire by default.
|
|
11
|
+
# To make URLs expire, pass the +expires_in+ option when generating the URL:
|
|
12
|
+
#
|
|
13
|
+
# rails_storage_proxy_url(representation, expires_in: 1.minute)
|
|
14
|
+
#
|
|
15
|
+
# Or set the default for all Active Storage URLs:
|
|
16
|
+
#
|
|
17
|
+
# config.active_storage.urls_expire_in = 1.day
|
|
18
|
+
#
|
|
19
|
+
# WARNING: All Active Storage controllers are publicly accessible by default.
|
|
20
|
+
# Anyone who knows the URL can access the file, even if the rest of your application requires
|
|
21
|
+
# authentication. If your files require access control consider implementing
|
|
8
22
|
# {Authenticated Controllers}[https://guides.rubyonrails.org/active_storage_overview.html#authenticated-controllers].
|
|
9
23
|
class ActiveStorage::Representations::ProxyController < ActiveStorage::Representations::BaseController
|
|
10
24
|
include ActiveStorage::Streaming
|
|
@@ -1,10 +1,27 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
#
|
|
3
|
+
# Finds a representation by a +signed_id+ and a +variation_key+, and redirects to a representation's expiring
|
|
4
|
+
# service URL.
|
|
4
5
|
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
6
|
+
# The +signed_id+s make URLs hard to guess but permanent by design, allowing the URLs to be cached.
|
|
7
|
+
#
|
|
8
|
+
# The URLs created for this controller are set to never expire by default.
|
|
9
|
+
# To make URLs expire, pass the +expires_in+ option when generating the URL:
|
|
10
|
+
#
|
|
11
|
+
# rails_storage_redirect_url(representation, expires_in: 1.minute)
|
|
12
|
+
#
|
|
13
|
+
# Or set the default for all Active Storage URLs:
|
|
14
|
+
#
|
|
15
|
+
# config.active_storage.urls_expire_in = 1.day
|
|
16
|
+
#
|
|
17
|
+
# The service URLs are set to expire in 5 minutes by default.
|
|
18
|
+
# The default can be changed for all service URLs:
|
|
19
|
+
#
|
|
20
|
+
# config.active_storage.service_urls_expire_in = 1.hour
|
|
21
|
+
#
|
|
22
|
+
# WARNING: All Active Storage controllers are publicly accessible by default.
|
|
23
|
+
# Anyone who knows the URL can access the file, even if the rest of your application requires
|
|
24
|
+
# authentication. If your files require access control consider implementing
|
|
8
25
|
# {Authenticated Controllers}[https://guides.rubyonrails.org/active_storage_overview.html#authenticated-controllers].
|
|
9
26
|
class ActiveStorage::Representations::RedirectController < ActiveStorage::Representations::BaseController
|
|
10
27
|
def show
|
|
@@ -34,7 +34,7 @@ class ActiveStorage::Attachment < ActiveStorage::Record
|
|
|
34
34
|
delegate :signed_id, to: :blob
|
|
35
35
|
|
|
36
36
|
after_create_commit :mirror_blob_later, :analyze_blob_later, :transform_variants_later
|
|
37
|
-
after_destroy_commit :
|
|
37
|
+
after_destroy_commit :purge_dependent_blob
|
|
38
38
|
|
|
39
39
|
##
|
|
40
40
|
# :singleton-method:
|
|
@@ -147,8 +147,12 @@ class ActiveStorage::Attachment < ActiveStorage::Record
|
|
|
147
147
|
end
|
|
148
148
|
end
|
|
149
149
|
|
|
150
|
-
def
|
|
151
|
-
|
|
150
|
+
def purge_dependent_blob
|
|
151
|
+
if dependent == :purge_later
|
|
152
|
+
blob&.purge_later
|
|
153
|
+
elsif dependent == :purge
|
|
154
|
+
blob&.purge
|
|
155
|
+
end
|
|
152
156
|
end
|
|
153
157
|
|
|
154
158
|
def dependent
|
|
@@ -282,6 +282,16 @@ class ActiveStorage::Blob < ActiveStorage::Record
|
|
|
282
282
|
service.compose(keys, key, **service_metadata)
|
|
283
283
|
end
|
|
284
284
|
|
|
285
|
+
def service_metadata # :nodoc:
|
|
286
|
+
if forcibly_serve_as_binary?
|
|
287
|
+
{ content_type: ActiveStorage.binary_content_type, disposition: :attachment, filename: filename, custom_metadata: custom_metadata }
|
|
288
|
+
elsif !allowed_inline?
|
|
289
|
+
{ content_type: content_type, disposition: :attachment, filename: filename, custom_metadata: custom_metadata }
|
|
290
|
+
else
|
|
291
|
+
{ content_type: content_type, custom_metadata: custom_metadata }
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
|
|
285
295
|
# Downloads the file associated with this blob. If no block is given, the entire file is read into memory and returned.
|
|
286
296
|
# That'll use a lot of RAM for very large files. If a block is given, then the download is streamed and yielded in chunks.
|
|
287
297
|
def download(&block)
|
|
@@ -371,16 +381,6 @@ class ActiveStorage::Blob < ActiveStorage::Record
|
|
|
371
381
|
ActiveStorage.web_image_content_types.include?(content_type)
|
|
372
382
|
end
|
|
373
383
|
|
|
374
|
-
def service_metadata
|
|
375
|
-
if forcibly_serve_as_binary?
|
|
376
|
-
{ content_type: ActiveStorage.binary_content_type, disposition: :attachment, filename: filename, custom_metadata: custom_metadata }
|
|
377
|
-
elsif !allowed_inline?
|
|
378
|
-
{ content_type: content_type, disposition: :attachment, filename: filename, custom_metadata: custom_metadata }
|
|
379
|
-
else
|
|
380
|
-
{ content_type: content_type, custom_metadata: custom_metadata }
|
|
381
|
-
end
|
|
382
|
-
end
|
|
383
|
-
|
|
384
384
|
def touch_attachments
|
|
385
385
|
attachments.then do |relation|
|
|
386
386
|
if ActiveStorage.touch_attachment_records
|
|
@@ -389,7 +389,7 @@ class ActiveStorage::Blob < ActiveStorage::Record
|
|
|
389
389
|
relation
|
|
390
390
|
end
|
|
391
391
|
end.each do |attachment|
|
|
392
|
-
attachment.touch
|
|
392
|
+
attachment.touch unless attachment.new_record?
|
|
393
393
|
end
|
|
394
394
|
end
|
|
395
395
|
|
|
@@ -78,7 +78,7 @@ class ActiveStorage::Variant
|
|
|
78
78
|
#
|
|
79
79
|
# Use <tt>url_for(variant)</tt> (or the implied form, like <tt>link_to variant</tt> or <tt>redirect_to variant</tt>) to get the stable URL
|
|
80
80
|
# for a variant that points to the ActiveStorage::Representations::ProxyController or ActiveStorage::Representations::RedirectController,
|
|
81
|
-
# which in turn will use this +
|
|
81
|
+
# which in turn will use this +url+ method for its redirection.
|
|
82
82
|
def url(expires_in: ActiveStorage.service_urls_expire_in, disposition: :inline)
|
|
83
83
|
service.url key, expires_in: expires_in, disposition: disposition, filename: filename, content_type: content_type
|
|
84
84
|
end
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module ActiveStorage
|
|
4
4
|
class Attached::Changes::CreateMany # :nodoc:
|
|
5
|
-
attr_reader :name, :
|
|
5
|
+
attr_reader :name, :attachables, :pending_uploads
|
|
6
|
+
attr_accessor :record
|
|
6
7
|
|
|
7
8
|
def initialize(name, record, attachables, pending_uploads: [])
|
|
8
9
|
@name, @record, @attachables = name, record, Array(attachables)
|
|
@@ -5,7 +5,8 @@ require "action_dispatch/http/upload"
|
|
|
5
5
|
|
|
6
6
|
module ActiveStorage
|
|
7
7
|
class Attached::Changes::CreateOne # :nodoc:
|
|
8
|
-
attr_reader :name, :
|
|
8
|
+
attr_reader :name, :attachable
|
|
9
|
+
attr_accessor :record
|
|
9
10
|
|
|
10
11
|
def initialize(name, record, attachable)
|
|
11
12
|
@name, @record, @attachable = name, record, attachable
|
|
@@ -75,7 +75,7 @@ module ActiveStorage
|
|
|
75
75
|
# The +:dependent+ option defaults to +:purge_later+. This means the attachment will be
|
|
76
76
|
# purged (i.e. destroyed) in the background whenever the record is destroyed.
|
|
77
77
|
# If an ActiveJob::Backend queue adapter is not set in the application set it to
|
|
78
|
-
#
|
|
78
|
+
# +:purge+ instead.
|
|
79
79
|
#
|
|
80
80
|
# If you need the attachment to use a service which differs from the globally configured one,
|
|
81
81
|
# pass the +:service+ option. For example:
|
|
@@ -177,7 +177,7 @@ module ActiveStorage
|
|
|
177
177
|
# The +:dependent+ option defaults to +:purge_later+. This means the attachments will be
|
|
178
178
|
# purged (i.e. destroyed) in the background whenever the record is destroyed.
|
|
179
179
|
# If an ActiveJob::Backend queue adapter is not set in the application set it to
|
|
180
|
-
#
|
|
180
|
+
# +:purge+ instead.
|
|
181
181
|
#
|
|
182
182
|
# If you need the attachment to use a service which differs from the globally configured one,
|
|
183
183
|
# pass the +:service+ option. For example:
|
|
@@ -278,6 +278,8 @@ module ActiveStorage
|
|
|
278
278
|
end
|
|
279
279
|
end
|
|
280
280
|
|
|
281
|
+
attr_writer :attachment_changes # :nodoc:
|
|
282
|
+
|
|
281
283
|
def attachment_changes # :nodoc:
|
|
282
284
|
@attachment_changes ||= {}
|
|
283
285
|
end
|
|
@@ -295,5 +297,14 @@ module ActiveStorage
|
|
|
295
297
|
def reload(*) # :nodoc:
|
|
296
298
|
super.tap { @attachment_changes = nil }
|
|
297
299
|
end
|
|
300
|
+
|
|
301
|
+
def becomes(klass) # :nodoc:
|
|
302
|
+
super.tap do |became|
|
|
303
|
+
attachment_changes = @attachment_changes&.each_value do |change|
|
|
304
|
+
change.record = became
|
|
305
|
+
end
|
|
306
|
+
became.attachment_changes = attachment_changes
|
|
307
|
+
end
|
|
308
|
+
end
|
|
298
309
|
end
|
|
299
310
|
end
|
|
@@ -45,6 +45,12 @@ module ActiveStorage
|
|
|
45
45
|
!attached?
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
+
# Returns the attachment record's JSON representation, or +nil+ when no
|
|
49
|
+
# attachment is present.
|
|
50
|
+
def as_json(options = nil)
|
|
51
|
+
attached? ? attachment.as_json(options) : nil
|
|
52
|
+
end
|
|
53
|
+
|
|
48
54
|
# Attaches an +attachable+ to the record.
|
|
49
55
|
#
|
|
50
56
|
# If the record is persisted and unchanged, the attachment is saved to
|
|
@@ -115,6 +115,16 @@ module ActiveStorage
|
|
|
115
115
|
Please add `gem "image_processing", "~> 1.2"` to your Gemfile
|
|
116
116
|
or set `config.active_storage.variant_processor = :disabled`.
|
|
117
117
|
WARNING
|
|
118
|
+
when /ruby-vips/
|
|
119
|
+
ActiveStorage.logger.warn <<~WARNING.squish
|
|
120
|
+
Generating image variants with libvips requires the ruby-vips gem.
|
|
121
|
+
Please add `gem "ruby-vips", "~> 2.3"` to your Gemfile.
|
|
122
|
+
WARNING
|
|
123
|
+
when /mini_magick/
|
|
124
|
+
ActiveStorage.logger.warn <<~WARNING.squish
|
|
125
|
+
Generating image variants with ImageMagick requires the mini_magick gem.
|
|
126
|
+
Please add `gem "mini_magick", "~> 5.0"` to your Gemfile.
|
|
127
|
+
WARNING
|
|
118
128
|
else
|
|
119
129
|
raise
|
|
120
130
|
end
|
|
@@ -7,7 +7,7 @@ module ActiveStorage
|
|
|
7
7
|
# Wraps a set of mirror services and provides a single ActiveStorage::Service object that will all
|
|
8
8
|
# have the files uploaded to them. A +primary+ service is designated to answer calls to:
|
|
9
9
|
# * +download+
|
|
10
|
-
# * +
|
|
10
|
+
# * +exist?+
|
|
11
11
|
# * +url+
|
|
12
12
|
# * +url_for_direct_upload+
|
|
13
13
|
# * +headers_for_direct_upload+
|
|
@@ -66,10 +66,12 @@ module ActiveStorage
|
|
|
66
66
|
def mirror(key, checksum:)
|
|
67
67
|
instrument :mirror, key: key, checksum: checksum do
|
|
68
68
|
if (mirrors_in_need_of_mirroring = mirrors.select { |service| !service.exist?(key) }).any?
|
|
69
|
-
|
|
69
|
+
metadata = ActiveStorage::Blob.find_by(key: key)&.service_metadata || {}
|
|
70
|
+
|
|
71
|
+
primary.open(key, checksum: checksum, verify: checksum.present?) do |io|
|
|
70
72
|
mirrors_in_need_of_mirroring.each do |service|
|
|
71
73
|
io.rewind
|
|
72
|
-
service.upload key, io, checksum: checksum
|
|
74
|
+
service.upload key, io, checksum: checksum, **metadata
|
|
73
75
|
end
|
|
74
76
|
end
|
|
75
77
|
end
|
data/lib/active_storage.rb
CHANGED
|
@@ -34,6 +34,7 @@ require "active_storage/deprecator"
|
|
|
34
34
|
require "active_storage/errors"
|
|
35
35
|
|
|
36
36
|
require "marcel"
|
|
37
|
+
require "openssl"
|
|
37
38
|
|
|
38
39
|
# :markup: markdown
|
|
39
40
|
# :include: ../README.md
|
|
@@ -358,6 +359,9 @@ module ActiveStorage
|
|
|
358
359
|
mattr_accessor :touch_attachment_records, default: true
|
|
359
360
|
mattr_accessor :urls_expire_in
|
|
360
361
|
|
|
362
|
+
# Configures the mount point for the default Active Storage routes. Accepts any
|
|
363
|
+
# value supported by `scope`, such as a string path prefix or a hash of routing
|
|
364
|
+
# options.
|
|
361
365
|
mattr_accessor :routes_prefix, default: "/rails/active_storage"
|
|
362
366
|
mattr_accessor :draw_routes, default: true
|
|
363
367
|
mattr_accessor :resolve_model_to_route, default: :rails_storage_redirect
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activestorage
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 8.1.
|
|
4
|
+
version: 8.1.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Heinemeier Hansson
|
|
@@ -15,56 +15,56 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - '='
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 8.1.
|
|
18
|
+
version: 8.1.4
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - '='
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 8.1.
|
|
25
|
+
version: 8.1.4
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: actionpack
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
30
|
- - '='
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: 8.1.
|
|
32
|
+
version: 8.1.4
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - '='
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: 8.1.
|
|
39
|
+
version: 8.1.4
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: activejob
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
|
43
43
|
requirements:
|
|
44
44
|
- - '='
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: 8.1.
|
|
46
|
+
version: 8.1.4
|
|
47
47
|
type: :runtime
|
|
48
48
|
prerelease: false
|
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
50
|
requirements:
|
|
51
51
|
- - '='
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: 8.1.
|
|
53
|
+
version: 8.1.4
|
|
54
54
|
- !ruby/object:Gem::Dependency
|
|
55
55
|
name: activerecord
|
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
|
57
57
|
requirements:
|
|
58
58
|
- - '='
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
|
-
version: 8.1.
|
|
60
|
+
version: 8.1.4
|
|
61
61
|
type: :runtime
|
|
62
62
|
prerelease: false
|
|
63
63
|
version_requirements: !ruby/object:Gem::Requirement
|
|
64
64
|
requirements:
|
|
65
65
|
- - '='
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
|
-
version: 8.1.
|
|
67
|
+
version: 8.1.4
|
|
68
68
|
- !ruby/object:Gem::Dependency
|
|
69
69
|
name: marcel
|
|
70
70
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -193,10 +193,10 @@ licenses:
|
|
|
193
193
|
- MIT
|
|
194
194
|
metadata:
|
|
195
195
|
bug_tracker_uri: https://github.com/rails/rails/issues
|
|
196
|
-
changelog_uri: https://github.com/rails/rails/blob/v8.1.
|
|
197
|
-
documentation_uri: https://api.rubyonrails.org/v8.1.
|
|
196
|
+
changelog_uri: https://github.com/rails/rails/blob/v8.1.4/activestorage/CHANGELOG.md
|
|
197
|
+
documentation_uri: https://api.rubyonrails.org/v8.1.4/
|
|
198
198
|
mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
|
|
199
|
-
source_code_uri: https://github.com/rails/rails/tree/v8.1.
|
|
199
|
+
source_code_uri: https://github.com/rails/rails/tree/v8.1.4/activestorage
|
|
200
200
|
rubygems_mfa_required: 'true'
|
|
201
201
|
rdoc_options: []
|
|
202
202
|
require_paths:
|
|
@@ -212,7 +212,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
212
212
|
- !ruby/object:Gem::Version
|
|
213
213
|
version: '0'
|
|
214
214
|
requirements: []
|
|
215
|
-
rubygems_version: 4.0.
|
|
215
|
+
rubygems_version: 4.0.20
|
|
216
216
|
specification_version: 4
|
|
217
217
|
summary: Local and cloud file storage framework.
|
|
218
218
|
test_files: []
|