activestorage 7.2.2.1 → 8.1.3
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 +126 -55
- data/README.md +8 -5
- data/app/assets/javascripts/activestorage.esm.js +38 -2
- data/app/assets/javascripts/activestorage.js +38 -1
- data/app/controllers/active_storage/direct_uploads_controller.rb +1 -1
- data/app/controllers/active_storage/disk_controller.rb +6 -2
- data/app/controllers/concerns/active_storage/streaming.rb +17 -1
- data/app/javascript/activestorage/direct_upload_controller.js +48 -1
- data/app/javascript/activestorage/index.js +2 -1
- data/app/models/active_storage/blob/representable.rb +71 -5
- data/app/models/active_storage/blob.rb +25 -21
- data/app/models/active_storage/filename.rb +2 -1
- data/app/models/active_storage/variant.rb +12 -12
- data/app/models/active_storage/variation.rb +1 -1
- data/lib/active_storage/analyzer/image_analyzer/image_magick.rb +11 -4
- data/lib/active_storage/analyzer/image_analyzer/vips.rb +23 -5
- data/lib/active_storage/analyzer/image_analyzer.rb +5 -0
- data/lib/active_storage/attached/changes/create_one.rb +1 -1
- data/lib/active_storage/attached/model.rb +41 -18
- data/lib/active_storage/attached.rb +0 -1
- data/lib/active_storage/engine.rb +38 -7
- data/lib/active_storage/errors.rb +4 -0
- data/lib/active_storage/fixture_set.rb +1 -1
- data/lib/active_storage/gem_version.rb +4 -4
- data/lib/active_storage/log_subscriber.rb +1 -1
- data/lib/active_storage/service/configurator.rb +6 -0
- data/lib/active_storage/service/disk_service.rb +46 -2
- data/lib/active_storage/service/gcs_service.rb +15 -5
- data/lib/active_storage/service/mirror_service.rb +13 -4
- data/lib/active_storage/service/registry.rb +6 -0
- data/lib/active_storage/service/s3_service.rb +19 -4
- data/lib/active_storage/service.rb +5 -1
- data/lib/active_storage/structured_event_subscriber.rb +79 -0
- data/lib/active_storage/transformers/image_magick.rb +72 -0
- data/lib/active_storage/transformers/image_processing_transformer.rb +5 -67
- data/lib/active_storage/transformers/null_transformer.rb +12 -0
- data/lib/active_storage/transformers/vips.rb +11 -0
- data/lib/active_storage.rb +19 -3
- metadata +19 -19
- data/lib/active_storage/service/azure_storage_service.rb +0 -194
|
@@ -144,6 +144,21 @@ module ActiveStorage
|
|
|
144
144
|
end
|
|
145
145
|
end
|
|
146
146
|
|
|
147
|
+
# Returns the IAM client used for direct uploads and signed URLs.
|
|
148
|
+
# By default, the authorization for the IAM client is set to
|
|
149
|
+
# {Application Default Credentials}[https://docs.cloud.google.com/docs/authentication/application-default-credentials],
|
|
150
|
+
# fetched once at instantiation time, then refreshed automatically when expired.
|
|
151
|
+
# This can be set to a different value to use other authorization methods.
|
|
152
|
+
#
|
|
153
|
+
# ActiveStorage::Blob.service.iam_client.authorization = Google::Auth::ImpersonatedServiceAccountCredentials.new(options)
|
|
154
|
+
def iam_client
|
|
155
|
+
@iam_client ||= Google::Apis::IamcredentialsV1::IAMCredentialsService.new.tap do |client|
|
|
156
|
+
client.authorization ||= Google::Auth.get_application_default(["https://www.googleapis.com/auth/iam"])
|
|
157
|
+
rescue
|
|
158
|
+
nil
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
147
162
|
private
|
|
148
163
|
def private_url(key, expires_in:, filename:, content_type:, disposition:, **)
|
|
149
164
|
args = {
|
|
@@ -211,11 +226,6 @@ module ActiveStorage
|
|
|
211
226
|
def signer
|
|
212
227
|
# https://googleapis.dev/ruby/google-cloud-storage/latest/Google/Cloud/Storage/Project.html#signed_url-instance_method
|
|
213
228
|
lambda do |string_to_sign|
|
|
214
|
-
iam_client = Google::Apis::IamcredentialsV1::IAMCredentialsService.new
|
|
215
|
-
|
|
216
|
-
scopes = ["https://www.googleapis.com/auth/iam"]
|
|
217
|
-
iam_client.authorization = Google::Auth.get_application_default(scopes)
|
|
218
|
-
|
|
219
229
|
request = Google::Apis::IamcredentialsV1::SignBlobRequest.new(
|
|
220
230
|
payload: string_to_sign
|
|
221
231
|
)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "active_support/core_ext/module/delegation"
|
|
4
3
|
|
|
5
4
|
module ActiveStorage
|
|
6
5
|
# = Active Storage Mirror \Service
|
|
@@ -30,6 +29,14 @@ module ActiveStorage
|
|
|
30
29
|
|
|
31
30
|
def initialize(primary:, mirrors:)
|
|
32
31
|
@primary, @mirrors = primary, mirrors
|
|
32
|
+
@executor = Concurrent::ThreadPoolExecutor.new(
|
|
33
|
+
name: "ActiveStorage-mirror-service",
|
|
34
|
+
min_threads: 1,
|
|
35
|
+
max_threads: mirrors.size,
|
|
36
|
+
max_queue: 0,
|
|
37
|
+
fallback_policy: :caller_runs,
|
|
38
|
+
idle_time: 60
|
|
39
|
+
)
|
|
33
40
|
end
|
|
34
41
|
|
|
35
42
|
# Upload the +io+ to the +key+ specified to all services. The upload to the primary service is done synchronously
|
|
@@ -75,10 +82,12 @@ module ActiveStorage
|
|
|
75
82
|
end
|
|
76
83
|
|
|
77
84
|
def perform_across_services(method, *args)
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
85
|
+
tasks = each_service.collect do |service|
|
|
86
|
+
Concurrent::Promise.execute(executor: @executor) do
|
|
87
|
+
service.public_send method, *args
|
|
88
|
+
end
|
|
81
89
|
end
|
|
90
|
+
tasks.each(&:value!)
|
|
82
91
|
end
|
|
83
92
|
end
|
|
84
93
|
end
|
|
@@ -22,6 +22,12 @@ module ActiveStorage
|
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
def inspect # :nodoc:
|
|
26
|
+
attrs = configurations.any? ?
|
|
27
|
+
" configurations=[#{configurations.keys.map(&:inspect).join(", ")}]" : ""
|
|
28
|
+
"#<#{self.class}#{attrs}>"
|
|
29
|
+
end
|
|
30
|
+
|
|
25
31
|
private
|
|
26
32
|
attr_reader :configurations, :services
|
|
27
33
|
|
|
@@ -16,6 +16,7 @@ module ActiveStorage
|
|
|
16
16
|
|
|
17
17
|
def initialize(bucket:, upload: {}, public: false, **options)
|
|
18
18
|
@client = Aws::S3::Resource.new(**options)
|
|
19
|
+
@transfer_manager = Aws::S3::TransferManager.new(client: @client.client) if defined?(Aws::S3::TransferManager)
|
|
19
20
|
@bucket = @client.bucket(bucket)
|
|
20
21
|
|
|
21
22
|
@multipart_upload_threshold = upload.delete(:multipart_threshold) || 100.megabytes
|
|
@@ -100,7 +101,8 @@ module ActiveStorage
|
|
|
100
101
|
def compose(source_keys, destination_key, filename: nil, content_type: nil, disposition: nil, custom_metadata: {})
|
|
101
102
|
content_disposition = content_disposition_with(type: disposition, filename: filename) if disposition && filename
|
|
102
103
|
|
|
103
|
-
|
|
104
|
+
upload_stream(
|
|
105
|
+
key: destination_key,
|
|
104
106
|
content_type: content_type,
|
|
105
107
|
content_disposition: content_disposition,
|
|
106
108
|
part_size: MINIMUM_UPLOAD_PART_SIZE,
|
|
@@ -116,6 +118,14 @@ module ActiveStorage
|
|
|
116
118
|
end
|
|
117
119
|
|
|
118
120
|
private
|
|
121
|
+
def upload_stream(key:, **options, &block)
|
|
122
|
+
if @transfer_manager
|
|
123
|
+
@transfer_manager.upload_stream(key: key, bucket: bucket.name, **options, &block)
|
|
124
|
+
else
|
|
125
|
+
object_for(key).upload_stream(**options, &block)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
119
129
|
def private_url(key, expires_in:, filename:, disposition:, content_type:, **client_opts)
|
|
120
130
|
object_for(key).presigned_url :get, expires_in: expires_in.to_i,
|
|
121
131
|
response_content_disposition: content_disposition_with(type: disposition, filename: filename),
|
|
@@ -126,7 +136,6 @@ module ActiveStorage
|
|
|
126
136
|
object_for(key).public_url(**client_opts)
|
|
127
137
|
end
|
|
128
138
|
|
|
129
|
-
|
|
130
139
|
MAXIMUM_UPLOAD_PARTS_COUNT = 10000
|
|
131
140
|
MINIMUM_UPLOAD_PART_SIZE = 5.megabytes
|
|
132
141
|
|
|
@@ -139,12 +148,18 @@ module ActiveStorage
|
|
|
139
148
|
def upload_with_multipart(key, io, content_type: nil, content_disposition: nil, custom_metadata: {})
|
|
140
149
|
part_size = [ io.size.fdiv(MAXIMUM_UPLOAD_PARTS_COUNT).ceil, MINIMUM_UPLOAD_PART_SIZE ].max
|
|
141
150
|
|
|
142
|
-
|
|
151
|
+
upload_stream(
|
|
152
|
+
key: key,
|
|
153
|
+
content_type: content_type,
|
|
154
|
+
content_disposition: content_disposition,
|
|
155
|
+
part_size: part_size,
|
|
156
|
+
metadata: custom_metadata,
|
|
157
|
+
**upload_options
|
|
158
|
+
) do |out|
|
|
143
159
|
IO.copy_stream(io, out)
|
|
144
160
|
end
|
|
145
161
|
end
|
|
146
162
|
|
|
147
|
-
|
|
148
163
|
def object_for(key)
|
|
149
164
|
bucket.object(key)
|
|
150
165
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "active_storage/log_subscriber"
|
|
4
|
+
require "active_storage/structured_event_subscriber"
|
|
4
5
|
require "active_storage/downloader"
|
|
5
6
|
require "action_dispatch"
|
|
6
7
|
require "action_dispatch/http/content_disposition"
|
|
@@ -15,7 +16,6 @@ module ActiveStorage
|
|
|
15
16
|
# * +Disk+, to manage attachments saved directly on the hard drive.
|
|
16
17
|
# * +GCS+, to manage attachments through Google Cloud Storage.
|
|
17
18
|
# * +S3+, to manage attachments through Amazon S3.
|
|
18
|
-
# * +AzureStorage+, to manage attachments through Microsoft Azure Storage.
|
|
19
19
|
# * +Mirror+, to be able to use several services to manage attachments.
|
|
20
20
|
#
|
|
21
21
|
# Inside a \Rails application, you can set-up your services through the
|
|
@@ -148,6 +148,10 @@ module ActiveStorage
|
|
|
148
148
|
@public
|
|
149
149
|
end
|
|
150
150
|
|
|
151
|
+
def inspect # :nodoc:
|
|
152
|
+
"#<#{self.class}#{name.present? ? " name=#{name.inspect}" : ""}>"
|
|
153
|
+
end
|
|
154
|
+
|
|
151
155
|
private
|
|
152
156
|
def private_url(key, expires_in:, filename:, disposition:, content_type:, **)
|
|
153
157
|
raise NotImplementedError
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/structured_event_subscriber"
|
|
4
|
+
|
|
5
|
+
module ActiveStorage
|
|
6
|
+
class StructuredEventSubscriber < ActiveSupport::StructuredEventSubscriber # :nodoc:
|
|
7
|
+
def service_upload(event)
|
|
8
|
+
emit_event("active_storage.service_upload",
|
|
9
|
+
key: event.payload[:key],
|
|
10
|
+
checksum: event.payload[:checksum],
|
|
11
|
+
duration_ms: event.duration.round(2),
|
|
12
|
+
)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def service_download(event)
|
|
16
|
+
emit_event("active_storage.service_download",
|
|
17
|
+
key: event.payload[:key],
|
|
18
|
+
duration_ms: event.duration.round(2),
|
|
19
|
+
)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def service_streaming_download(event)
|
|
23
|
+
emit_event("active_storage.service_streaming_download",
|
|
24
|
+
key: event.payload[:key],
|
|
25
|
+
duration_ms: event.duration.round(2),
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def preview(event)
|
|
30
|
+
emit_event("active_storage.preview",
|
|
31
|
+
key: event.payload[:key],
|
|
32
|
+
duration_ms: event.duration.round(2),
|
|
33
|
+
)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def service_delete(event)
|
|
37
|
+
emit_event("active_storage.service_delete",
|
|
38
|
+
key: event.payload[:key],
|
|
39
|
+
duration_ms: event.duration.round(2),
|
|
40
|
+
)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def service_delete_prefixed(event)
|
|
44
|
+
emit_event("active_storage.service_delete_prefixed",
|
|
45
|
+
prefix: event.payload[:prefix],
|
|
46
|
+
duration_ms: event.duration.round(2),
|
|
47
|
+
)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def service_exist(event)
|
|
51
|
+
emit_debug_event("active_storage.service_exist",
|
|
52
|
+
key: event.payload[:key],
|
|
53
|
+
exist: event.payload[:exist],
|
|
54
|
+
duration_ms: event.duration.round(2),
|
|
55
|
+
)
|
|
56
|
+
end
|
|
57
|
+
debug_only :service_exist
|
|
58
|
+
|
|
59
|
+
def service_url(event)
|
|
60
|
+
emit_debug_event("active_storage.service_url",
|
|
61
|
+
key: event.payload[:key],
|
|
62
|
+
url: event.payload[:url],
|
|
63
|
+
duration_ms: event.duration.round(2),
|
|
64
|
+
)
|
|
65
|
+
end
|
|
66
|
+
debug_only :service_url
|
|
67
|
+
|
|
68
|
+
def service_mirror(event)
|
|
69
|
+
emit_debug_event("active_storage.service_mirror",
|
|
70
|
+
key: event.payload[:key],
|
|
71
|
+
checksum: event.payload[:checksum],
|
|
72
|
+
duration_ms: event.duration.round(2),
|
|
73
|
+
)
|
|
74
|
+
end
|
|
75
|
+
debug_only :service_mirror
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
ActiveStorage::StructuredEventSubscriber.attach_to :active_storage
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveStorage
|
|
4
|
+
module Transformers
|
|
5
|
+
class ImageMagick < ImageProcessingTransformer
|
|
6
|
+
private
|
|
7
|
+
def processor
|
|
8
|
+
ImageProcessing::MiniMagick
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def validate_transformation(name, argument)
|
|
12
|
+
method_name = name.to_s.tr("-", "_")
|
|
13
|
+
|
|
14
|
+
unless ActiveStorage.supported_image_processing_methods.include?(method_name)
|
|
15
|
+
raise UnsupportedImageProcessingMethod, <<~ERROR.squish
|
|
16
|
+
The provided transformation method is not supported: #{method_name}.
|
|
17
|
+
ERROR
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
if argument.present?
|
|
21
|
+
if argument.is_a?(String) || argument.is_a?(Symbol)
|
|
22
|
+
validate_arg_string(argument)
|
|
23
|
+
elsif argument.is_a?(Array)
|
|
24
|
+
validate_arg_array(argument)
|
|
25
|
+
elsif argument.is_a?(Hash)
|
|
26
|
+
validate_arg_hash(argument)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
super
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def validate_arg_string(argument)
|
|
34
|
+
unsupported_arguments = ActiveStorage.unsupported_image_processing_arguments.any? do |bad_arg|
|
|
35
|
+
argument.to_s.downcase.include?(bad_arg)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
raise UnsupportedImageProcessingArgument if unsupported_arguments
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def validate_arg_array(argument)
|
|
42
|
+
argument.each do |arg|
|
|
43
|
+
if arg.is_a?(Integer) || arg.is_a?(Float)
|
|
44
|
+
next
|
|
45
|
+
elsif arg.is_a?(String) || arg.is_a?(Symbol)
|
|
46
|
+
validate_arg_string(arg)
|
|
47
|
+
elsif arg.is_a?(Array)
|
|
48
|
+
validate_arg_array(arg)
|
|
49
|
+
elsif arg.is_a?(Hash)
|
|
50
|
+
validate_arg_hash(arg)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def validate_arg_hash(argument)
|
|
56
|
+
argument.each do |key, value|
|
|
57
|
+
validate_arg_string(key)
|
|
58
|
+
|
|
59
|
+
if value.is_a?(Integer) || value.is_a?(Float)
|
|
60
|
+
next
|
|
61
|
+
elsif value.is_a?(String) || value.is_a?(Symbol)
|
|
62
|
+
validate_arg_string(value)
|
|
63
|
+
elsif value.is_a?(Array)
|
|
64
|
+
validate_arg_array(value)
|
|
65
|
+
elsif value.is_a?(Hash)
|
|
66
|
+
validate_arg_hash(value)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -25,22 +25,9 @@ module ActiveStorage
|
|
|
25
25
|
call
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
def processor
|
|
29
|
-
ImageProcessing.const_get(ActiveStorage.variant_processor.to_s.camelize)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
28
|
def operations
|
|
33
29
|
transformations.each_with_object([]) do |(name, argument), list|
|
|
34
|
-
|
|
35
|
-
validate_transformation(name, argument)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
if name.to_s == "combine_options"
|
|
39
|
-
raise ArgumentError, <<~ERROR.squish
|
|
40
|
-
Active Storage's ImageProcessing transformer doesn't support :combine_options,
|
|
41
|
-
as it always generates a single command.
|
|
42
|
-
ERROR
|
|
43
|
-
end
|
|
30
|
+
validate_transformation(name, argument)
|
|
44
31
|
|
|
45
32
|
if argument.present?
|
|
46
33
|
list << [ name, argument ]
|
|
@@ -49,61 +36,12 @@ module ActiveStorage
|
|
|
49
36
|
end
|
|
50
37
|
|
|
51
38
|
def validate_transformation(name, argument)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
One or more of the provided transformation methods is not supported.
|
|
39
|
+
if name.to_s == "combine_options"
|
|
40
|
+
raise ArgumentError, <<~ERROR.squish
|
|
41
|
+
Active Storage's ImageProcessing transformer doesn't support :combine_options,
|
|
42
|
+
as it always generates a single command.
|
|
57
43
|
ERROR
|
|
58
44
|
end
|
|
59
|
-
|
|
60
|
-
if argument.present?
|
|
61
|
-
if argument.is_a?(String) || argument.is_a?(Symbol)
|
|
62
|
-
validate_arg_string(argument)
|
|
63
|
-
elsif argument.is_a?(Array)
|
|
64
|
-
validate_arg_array(argument)
|
|
65
|
-
elsif argument.is_a?(Hash)
|
|
66
|
-
validate_arg_hash(argument)
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def validate_arg_string(argument)
|
|
72
|
-
unsupported_arguments = ActiveStorage.unsupported_image_processing_arguments.any? do |bad_arg|
|
|
73
|
-
argument.to_s.downcase.include?(bad_arg)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
raise UnsupportedImageProcessingArgument if unsupported_arguments
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def validate_arg_array(argument)
|
|
80
|
-
argument.each do |arg|
|
|
81
|
-
if arg.is_a?(Integer) || arg.is_a?(Float)
|
|
82
|
-
next
|
|
83
|
-
elsif arg.is_a?(String) || arg.is_a?(Symbol)
|
|
84
|
-
validate_arg_string(arg)
|
|
85
|
-
elsif arg.is_a?(Array)
|
|
86
|
-
validate_arg_array(arg)
|
|
87
|
-
elsif arg.is_a?(Hash)
|
|
88
|
-
validate_arg_hash(arg)
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def validate_arg_hash(argument)
|
|
94
|
-
argument.each do |key, value|
|
|
95
|
-
validate_arg_string(key)
|
|
96
|
-
|
|
97
|
-
if value.is_a?(Integer) || value.is_a?(Float)
|
|
98
|
-
next
|
|
99
|
-
elsif value.is_a?(String) || value.is_a?(Symbol)
|
|
100
|
-
validate_arg_string(value)
|
|
101
|
-
elsif value.is_a?(Array)
|
|
102
|
-
validate_arg_array(value)
|
|
103
|
-
elsif value.is_a?(Hash)
|
|
104
|
-
validate_arg_hash(value)
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
45
|
end
|
|
108
46
|
end
|
|
109
47
|
end
|
data/lib/active_storage.rb
CHANGED
|
@@ -27,6 +27,7 @@ require "active_record"
|
|
|
27
27
|
require "active_support"
|
|
28
28
|
require "active_support/rails"
|
|
29
29
|
require "active_support/core_ext/numeric/time"
|
|
30
|
+
require "active_support/core_ext/numeric/bytes"
|
|
30
31
|
|
|
31
32
|
require "active_storage/version"
|
|
32
33
|
require "active_storage/deprecator"
|
|
@@ -49,6 +50,8 @@ module ActiveStorage
|
|
|
49
50
|
mattr_accessor :verifier
|
|
50
51
|
mattr_accessor :variant_processor, default: :mini_magick
|
|
51
52
|
|
|
53
|
+
mattr_accessor :variant_transformer
|
|
54
|
+
|
|
52
55
|
mattr_accessor :queues, default: {}
|
|
53
56
|
|
|
54
57
|
mattr_accessor :previewers, default: []
|
|
@@ -72,7 +75,6 @@ module ActiveStorage
|
|
|
72
75
|
"annotate",
|
|
73
76
|
"antialias",
|
|
74
77
|
"append",
|
|
75
|
-
"apply",
|
|
76
78
|
"attenuate",
|
|
77
79
|
"authenticate",
|
|
78
80
|
"auto_gamma",
|
|
@@ -213,7 +215,6 @@ module ActiveStorage
|
|
|
213
215
|
"linewidth",
|
|
214
216
|
"liquid_rescale",
|
|
215
217
|
"list",
|
|
216
|
-
"loader",
|
|
217
218
|
"log",
|
|
218
219
|
"loop",
|
|
219
220
|
"lowlight_color",
|
|
@@ -276,7 +277,6 @@ module ActiveStorage
|
|
|
276
277
|
"rotate",
|
|
277
278
|
"sample",
|
|
278
279
|
"sampling_factor",
|
|
279
|
-
"saver",
|
|
280
280
|
"scale",
|
|
281
281
|
"scene",
|
|
282
282
|
"screen",
|
|
@@ -353,6 +353,7 @@ module ActiveStorage
|
|
|
353
353
|
]
|
|
354
354
|
mattr_accessor :unsupported_image_processing_arguments
|
|
355
355
|
|
|
356
|
+
mattr_accessor :streaming_chunk_max_size, default: 100.megabytes
|
|
356
357
|
mattr_accessor :service_urls_expire_in, default: 5.minutes
|
|
357
358
|
mattr_accessor :touch_attachment_records, default: true
|
|
358
359
|
mattr_accessor :urls_expire_in
|
|
@@ -363,12 +364,27 @@ module ActiveStorage
|
|
|
363
364
|
|
|
364
365
|
mattr_accessor :track_variants, default: false
|
|
365
366
|
|
|
367
|
+
singleton_class.attr_accessor :checksum_implementation
|
|
368
|
+
@checksum_implementation = OpenSSL::Digest::MD5
|
|
369
|
+
begin
|
|
370
|
+
@checksum_implementation.hexdigest("test")
|
|
371
|
+
rescue # OpenSSL may have MD5 disabled
|
|
372
|
+
require "digest/md5"
|
|
373
|
+
@checksum_implementation = Digest::MD5
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
singleton_class.attr_accessor :streaming_max_ranges
|
|
377
|
+
@streaming_max_ranges = 1
|
|
378
|
+
|
|
366
379
|
mattr_accessor :video_preview_arguments, default: "-y -vframes 1 -f image2"
|
|
367
380
|
|
|
368
381
|
module Transformers
|
|
369
382
|
extend ActiveSupport::Autoload
|
|
370
383
|
|
|
371
384
|
autoload :Transformer
|
|
385
|
+
autoload :NullTransformer
|
|
372
386
|
autoload :ImageProcessingTransformer
|
|
387
|
+
autoload :Vips
|
|
388
|
+
autoload :ImageMagick
|
|
373
389
|
end
|
|
374
390
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activestorage
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 8.1.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Heinemeier Hansson
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: activesupport
|
|
@@ -16,56 +15,56 @@ dependencies:
|
|
|
16
15
|
requirements:
|
|
17
16
|
- - '='
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version:
|
|
18
|
+
version: 8.1.3
|
|
20
19
|
type: :runtime
|
|
21
20
|
prerelease: false
|
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
22
|
requirements:
|
|
24
23
|
- - '='
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
|
-
version:
|
|
25
|
+
version: 8.1.3
|
|
27
26
|
- !ruby/object:Gem::Dependency
|
|
28
27
|
name: actionpack
|
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
|
30
29
|
requirements:
|
|
31
30
|
- - '='
|
|
32
31
|
- !ruby/object:Gem::Version
|
|
33
|
-
version:
|
|
32
|
+
version: 8.1.3
|
|
34
33
|
type: :runtime
|
|
35
34
|
prerelease: false
|
|
36
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
36
|
requirements:
|
|
38
37
|
- - '='
|
|
39
38
|
- !ruby/object:Gem::Version
|
|
40
|
-
version:
|
|
39
|
+
version: 8.1.3
|
|
41
40
|
- !ruby/object:Gem::Dependency
|
|
42
41
|
name: activejob
|
|
43
42
|
requirement: !ruby/object:Gem::Requirement
|
|
44
43
|
requirements:
|
|
45
44
|
- - '='
|
|
46
45
|
- !ruby/object:Gem::Version
|
|
47
|
-
version:
|
|
46
|
+
version: 8.1.3
|
|
48
47
|
type: :runtime
|
|
49
48
|
prerelease: false
|
|
50
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
50
|
requirements:
|
|
52
51
|
- - '='
|
|
53
52
|
- !ruby/object:Gem::Version
|
|
54
|
-
version:
|
|
53
|
+
version: 8.1.3
|
|
55
54
|
- !ruby/object:Gem::Dependency
|
|
56
55
|
name: activerecord
|
|
57
56
|
requirement: !ruby/object:Gem::Requirement
|
|
58
57
|
requirements:
|
|
59
58
|
- - '='
|
|
60
59
|
- !ruby/object:Gem::Version
|
|
61
|
-
version:
|
|
60
|
+
version: 8.1.3
|
|
62
61
|
type: :runtime
|
|
63
62
|
prerelease: false
|
|
64
63
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
64
|
requirements:
|
|
66
65
|
- - '='
|
|
67
66
|
- !ruby/object:Gem::Version
|
|
68
|
-
version:
|
|
67
|
+
version: 8.1.3
|
|
69
68
|
- !ruby/object:Gem::Dependency
|
|
70
69
|
name: marcel
|
|
71
70
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -174,15 +173,18 @@ files:
|
|
|
174
173
|
- lib/active_storage/previewer/video_previewer.rb
|
|
175
174
|
- lib/active_storage/reflection.rb
|
|
176
175
|
- lib/active_storage/service.rb
|
|
177
|
-
- lib/active_storage/service/azure_storage_service.rb
|
|
178
176
|
- lib/active_storage/service/configurator.rb
|
|
179
177
|
- lib/active_storage/service/disk_service.rb
|
|
180
178
|
- lib/active_storage/service/gcs_service.rb
|
|
181
179
|
- lib/active_storage/service/mirror_service.rb
|
|
182
180
|
- lib/active_storage/service/registry.rb
|
|
183
181
|
- lib/active_storage/service/s3_service.rb
|
|
182
|
+
- lib/active_storage/structured_event_subscriber.rb
|
|
183
|
+
- lib/active_storage/transformers/image_magick.rb
|
|
184
184
|
- lib/active_storage/transformers/image_processing_transformer.rb
|
|
185
|
+
- lib/active_storage/transformers/null_transformer.rb
|
|
185
186
|
- lib/active_storage/transformers/transformer.rb
|
|
187
|
+
- lib/active_storage/transformers/vips.rb
|
|
186
188
|
- lib/active_storage/version.rb
|
|
187
189
|
- lib/tasks/activestorage.rake
|
|
188
190
|
homepage: https://rubyonrails.org
|
|
@@ -190,12 +192,11 @@ licenses:
|
|
|
190
192
|
- MIT
|
|
191
193
|
metadata:
|
|
192
194
|
bug_tracker_uri: https://github.com/rails/rails/issues
|
|
193
|
-
changelog_uri: https://github.com/rails/rails/blob/
|
|
194
|
-
documentation_uri: https://api.rubyonrails.org/
|
|
195
|
+
changelog_uri: https://github.com/rails/rails/blob/v8.1.3/activestorage/CHANGELOG.md
|
|
196
|
+
documentation_uri: https://api.rubyonrails.org/v8.1.3/
|
|
195
197
|
mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
|
|
196
|
-
source_code_uri: https://github.com/rails/rails/tree/
|
|
198
|
+
source_code_uri: https://github.com/rails/rails/tree/v8.1.3/activestorage
|
|
197
199
|
rubygems_mfa_required: 'true'
|
|
198
|
-
post_install_message:
|
|
199
200
|
rdoc_options: []
|
|
200
201
|
require_paths:
|
|
201
202
|
- lib
|
|
@@ -203,15 +204,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
203
204
|
requirements:
|
|
204
205
|
- - ">="
|
|
205
206
|
- !ruby/object:Gem::Version
|
|
206
|
-
version: 3.
|
|
207
|
+
version: 3.2.0
|
|
207
208
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
208
209
|
requirements:
|
|
209
210
|
- - ">="
|
|
210
211
|
- !ruby/object:Gem::Version
|
|
211
212
|
version: '0'
|
|
212
213
|
requirements: []
|
|
213
|
-
rubygems_version:
|
|
214
|
-
signing_key:
|
|
214
|
+
rubygems_version: 4.0.6
|
|
215
215
|
specification_version: 4
|
|
216
216
|
summary: Local and cloud file storage framework.
|
|
217
217
|
test_files: []
|