activestorage 5.2.0.beta2 → 5.2.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activestorage might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +25 -0
- data/MIT-LICENSE +1 -1
- data/README.md +15 -1
- data/app/assets/javascripts/activestorage.js +1 -1
- data/app/controllers/active_storage/blobs_controller.rb +4 -6
- data/app/controllers/active_storage/previews_controller.rb +4 -6
- data/app/controllers/active_storage/variants_controller.rb +4 -6
- data/app/controllers/concerns/active_storage/set_blob.rb +16 -0
- data/app/javascript/activestorage/blob_record.js +17 -3
- data/app/javascript/activestorage/helpers.js +10 -1
- data/app/models/active_storage/attachment.rb +5 -1
- data/app/models/active_storage/blob.rb +15 -134
- data/app/models/active_storage/blob/analyzable.rb +57 -0
- data/app/models/active_storage/blob/identifiable.rb +11 -0
- data/app/models/active_storage/blob/representable.rb +93 -0
- data/app/models/active_storage/filename.rb +1 -1
- data/app/models/active_storage/filename/parameters.rb +1 -1
- data/app/models/active_storage/identification.rb +38 -0
- data/app/models/active_storage/variant.rb +51 -5
- data/app/models/active_storage/variation.rb +19 -5
- data/config/routes.rb +7 -7
- data/lib/active_storage.rb +8 -1
- data/lib/active_storage/analyzer.rb +1 -1
- data/lib/active_storage/analyzer/image_analyzer.rb +1 -2
- data/lib/active_storage/analyzer/video_analyzer.rb +51 -10
- data/lib/active_storage/attached/macros.rb +4 -4
- data/lib/active_storage/downloading.rb +16 -4
- data/lib/active_storage/engine.rb +18 -1
- data/lib/active_storage/errors.rb +7 -0
- data/lib/active_storage/gem_version.rb +1 -1
- data/lib/active_storage/log_subscriber.rb +4 -0
- data/lib/active_storage/previewer.rb +21 -5
- data/lib/active_storage/previewer/pdf_previewer.rb +10 -1
- data/lib/active_storage/previewer/video_previewer.rb +5 -1
- data/lib/active_storage/service.rb +8 -3
- data/lib/active_storage/service/azure_storage_service.rb +24 -8
- data/lib/active_storage/service/disk_service.rb +26 -24
- data/lib/active_storage/service/gcs_service.rb +21 -7
- data/lib/active_storage/service/mirror_service.rb +5 -0
- data/lib/active_storage/service/s3_service.rb +13 -7
- data/lib/tasks/activestorage.rake +5 -1
- metadata +43 -9
@@ -38,13 +38,13 @@ module ActiveStorage
|
|
38
38
|
end
|
39
39
|
CODE
|
40
40
|
|
41
|
-
has_one :"#{name}_attachment", -> { where(name: name) }, class_name: "ActiveStorage::Attachment", as: :record
|
41
|
+
has_one :"#{name}_attachment", -> { where(name: name) }, class_name: "ActiveStorage::Attachment", as: :record, inverse_of: :record
|
42
42
|
has_one :"#{name}_blob", through: :"#{name}_attachment", class_name: "ActiveStorage::Blob", source: :blob
|
43
43
|
|
44
44
|
scope :"with_attached_#{name}", -> { includes("#{name}_attachment": :blob) }
|
45
45
|
|
46
46
|
if dependent == :purge_later
|
47
|
-
|
47
|
+
after_destroy_commit { public_send(name).purge_later }
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -83,13 +83,13 @@ module ActiveStorage
|
|
83
83
|
end
|
84
84
|
CODE
|
85
85
|
|
86
|
-
has_many :"#{name}_attachments", -> { where(name: name) }, as: :record, class_name: "ActiveStorage::Attachment"
|
86
|
+
has_many :"#{name}_attachments", -> { where(name: name) }, as: :record, class_name: "ActiveStorage::Attachment", inverse_of: :record
|
87
87
|
has_many :"#{name}_blobs", through: :"#{name}_attachments", class_name: "ActiveStorage::Blob", source: :blob
|
88
88
|
|
89
89
|
scope :"with_attached_#{name}", -> { includes("#{name}_attachments": :blob) }
|
90
90
|
|
91
91
|
if dependent == :purge_later
|
92
|
-
|
92
|
+
after_destroy_commit { public_send(name).purge_later }
|
93
93
|
end
|
94
94
|
end
|
95
95
|
end
|
@@ -1,25 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "tmpdir"
|
4
|
+
|
3
5
|
module ActiveStorage
|
4
6
|
module Downloading
|
5
7
|
private
|
6
8
|
# Opens a new tempfile in #tempdir and copies blob data into it. Yields the tempfile.
|
7
|
-
def download_blob_to_tempfile
|
8
|
-
|
9
|
+
def download_blob_to_tempfile #:doc:
|
10
|
+
open_tempfile_for_blob do |file|
|
9
11
|
download_blob_to file
|
10
12
|
yield file
|
11
13
|
end
|
12
14
|
end
|
13
15
|
|
16
|
+
def open_tempfile_for_blob
|
17
|
+
tempfile = Tempfile.open([ "ActiveStorage", blob.filename.extension_with_delimiter ], tempdir)
|
18
|
+
|
19
|
+
begin
|
20
|
+
yield tempfile
|
21
|
+
ensure
|
22
|
+
tempfile.close!
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
14
26
|
# Efficiently downloads blob data into the given file.
|
15
|
-
def download_blob_to(file)
|
27
|
+
def download_blob_to(file) #:doc:
|
16
28
|
file.binmode
|
17
29
|
blob.download { |chunk| file.write(chunk) }
|
18
30
|
file.rewind
|
19
31
|
end
|
20
32
|
|
21
33
|
# Returns the directory in which tempfiles should be opened. Defaults to +Dir.tmpdir+.
|
22
|
-
def tempdir
|
34
|
+
def tempdir #:doc:
|
23
35
|
Dir.tmpdir
|
24
36
|
end
|
25
37
|
end
|
@@ -15,7 +15,20 @@ module ActiveStorage
|
|
15
15
|
|
16
16
|
config.active_storage = ActiveSupport::OrderedOptions.new
|
17
17
|
config.active_storage.previewers = [ ActiveStorage::Previewer::PDFPreviewer, ActiveStorage::Previewer::VideoPreviewer ]
|
18
|
-
config.active_storage.analyzers
|
18
|
+
config.active_storage.analyzers = [ ActiveStorage::Analyzer::ImageAnalyzer, ActiveStorage::Analyzer::VideoAnalyzer ]
|
19
|
+
config.active_storage.paths = ActiveSupport::OrderedOptions.new
|
20
|
+
|
21
|
+
config.active_storage.variable_content_types = %w( image/png image/gif image/jpg image/jpeg image/vnd.adobe.photoshop )
|
22
|
+
config.active_storage.content_types_to_serve_as_binary = %w(
|
23
|
+
text/html
|
24
|
+
text/javascript
|
25
|
+
image/svg+xml
|
26
|
+
application/postscript
|
27
|
+
application/x-shockwave-flash
|
28
|
+
text/xml
|
29
|
+
application/xml
|
30
|
+
application/xhtml+xml
|
31
|
+
)
|
19
32
|
|
20
33
|
config.eager_load_namespaces << ActiveStorage
|
21
34
|
|
@@ -25,6 +38,10 @@ module ActiveStorage
|
|
25
38
|
ActiveStorage.queue = app.config.active_storage.queue
|
26
39
|
ActiveStorage.previewers = app.config.active_storage.previewers || []
|
27
40
|
ActiveStorage.analyzers = app.config.active_storage.analyzers || []
|
41
|
+
ActiveStorage.paths = app.config.active_storage.paths || {}
|
42
|
+
|
43
|
+
ActiveStorage.variable_content_types = app.config.active_storage.variable_content_types || []
|
44
|
+
ActiveStorage.content_types_to_serve_as_binary = app.config.active_storage.content_types_to_serve_as_binary || []
|
28
45
|
end
|
29
46
|
end
|
30
47
|
|
@@ -18,6 +18,10 @@ module ActiveStorage
|
|
18
18
|
info event, color("Deleted file from key: #{key_in(event)}", RED)
|
19
19
|
end
|
20
20
|
|
21
|
+
def service_delete_prefixed(event)
|
22
|
+
info event, color("Deleted files by key prefix: #{event.payload[:prefix]}", RED)
|
23
|
+
end
|
24
|
+
|
21
25
|
def service_exist(event)
|
22
26
|
debug event, color("Checked if file exists at key: #{key_in(event)} (#{event.payload[:exist] ? "yes" : "no"})", BLUE)
|
23
27
|
end
|
@@ -42,17 +42,33 @@ module ActiveStorage
|
|
42
42
|
# end
|
43
43
|
#
|
44
44
|
# The output tempfile is opened in the directory returned by ActiveStorage::Downloading#tempdir.
|
45
|
-
def draw(*argv)
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
def draw(*argv) #:doc:
|
46
|
+
ActiveSupport::Notifications.instrument("preview.active_storage") do
|
47
|
+
open_tempfile_for_drawing do |file|
|
48
|
+
capture(*argv, to: file)
|
49
|
+
yield file
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def open_tempfile_for_drawing
|
55
|
+
tempfile = Tempfile.open("ActiveStorage", tempdir)
|
56
|
+
|
57
|
+
begin
|
58
|
+
yield tempfile
|
59
|
+
ensure
|
60
|
+
tempfile.close!
|
49
61
|
end
|
50
62
|
end
|
51
63
|
|
52
64
|
def capture(*argv, to:)
|
53
65
|
to.binmode
|
54
|
-
IO.popen(argv) { |out| IO.copy_stream(out, to) }
|
66
|
+
IO.popen(argv, err: File::NULL) { |out| IO.copy_stream(out, to) }
|
55
67
|
to.rewind
|
56
68
|
end
|
69
|
+
|
70
|
+
def logger #:doc:
|
71
|
+
ActiveStorage.logger
|
72
|
+
end
|
57
73
|
end
|
58
74
|
end
|
@@ -8,10 +8,19 @@ module ActiveStorage
|
|
8
8
|
|
9
9
|
def preview
|
10
10
|
download_blob_to_tempfile do |input|
|
11
|
-
|
11
|
+
draw_first_page_from input do |output|
|
12
12
|
yield io: output, filename: "#{blob.filename.base}.png", content_type: "image/png"
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
16
|
+
|
17
|
+
private
|
18
|
+
def draw_first_page_from(file, &block)
|
19
|
+
draw mutool_path, "draw", "-F", "png", "-o", "-", file.path, "1", &block
|
20
|
+
end
|
21
|
+
|
22
|
+
def mutool_path
|
23
|
+
ActiveStorage.paths[:mutool] || "mutool"
|
24
|
+
end
|
16
25
|
end
|
17
26
|
end
|
@@ -16,8 +16,12 @@ module ActiveStorage
|
|
16
16
|
|
17
17
|
private
|
18
18
|
def draw_relevant_frame_from(file, &block)
|
19
|
-
draw
|
19
|
+
draw ffmpeg_path, "-i", file.path, "-y", "-vcodec", "png",
|
20
20
|
"-vf", "thumbnail", "-vframes", "1", "-f", "image2", "-", &block
|
21
21
|
end
|
22
|
+
|
23
|
+
def ffmpeg_path
|
24
|
+
ActiveStorage.paths[:ffmpeg] || "ffmpeg"
|
25
|
+
end
|
22
26
|
end
|
23
27
|
end
|
@@ -78,6 +78,11 @@ module ActiveStorage
|
|
78
78
|
raise NotImplementedError
|
79
79
|
end
|
80
80
|
|
81
|
+
# Delete files at keys starting with the +prefix+.
|
82
|
+
def delete_prefixed(prefix)
|
83
|
+
raise NotImplementedError
|
84
|
+
end
|
85
|
+
|
81
86
|
# Return +true+ if a file exists at the +key+.
|
82
87
|
def exist?(key)
|
83
88
|
raise NotImplementedError
|
@@ -92,7 +97,7 @@ module ActiveStorage
|
|
92
97
|
|
93
98
|
# Returns a signed, temporary URL that a direct upload file can be PUT to on the +key+.
|
94
99
|
# The URL will be valid for the amount of seconds specified in +expires_in+.
|
95
|
-
# You
|
100
|
+
# You must also provide the +content_type+, +content_length+, and +checksum+ of the file
|
96
101
|
# that will be uploaded. All these attributes will be validated by the service upon upload.
|
97
102
|
def url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:)
|
98
103
|
raise NotImplementedError
|
@@ -104,10 +109,10 @@ module ActiveStorage
|
|
104
109
|
end
|
105
110
|
|
106
111
|
private
|
107
|
-
def instrument(operation,
|
112
|
+
def instrument(operation, payload = {}, &block)
|
108
113
|
ActiveSupport::Notifications.instrument(
|
109
114
|
"service_#{operation}.active_storage",
|
110
|
-
payload.merge(
|
115
|
+
payload.merge(service: service_name), &block)
|
111
116
|
end
|
112
117
|
|
113
118
|
def service_name
|
@@ -19,7 +19,7 @@ module ActiveStorage
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def upload(key, io, checksum: nil)
|
22
|
-
instrument :upload, key, checksum: checksum do
|
22
|
+
instrument :upload, key: key, checksum: checksum do
|
23
23
|
begin
|
24
24
|
blobs.create_block_blob(container, key, io, content_md5: checksum)
|
25
25
|
rescue Azure::Core::Http::HTTPError
|
@@ -30,11 +30,11 @@ module ActiveStorage
|
|
30
30
|
|
31
31
|
def download(key, &block)
|
32
32
|
if block_given?
|
33
|
-
instrument :streaming_download, key do
|
33
|
+
instrument :streaming_download, key: key do
|
34
34
|
stream(key, &block)
|
35
35
|
end
|
36
36
|
else
|
37
|
-
instrument :download, key do
|
37
|
+
instrument :download, key: key do
|
38
38
|
_, io = blobs.get_blob(container, key)
|
39
39
|
io.force_encoding(Encoding::BINARY)
|
40
40
|
end
|
@@ -42,17 +42,33 @@ module ActiveStorage
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def delete(key)
|
45
|
-
instrument :delete, key do
|
45
|
+
instrument :delete, key: key do
|
46
46
|
begin
|
47
47
|
blobs.delete_blob(container, key)
|
48
48
|
rescue Azure::Core::Http::HTTPError
|
49
|
-
|
49
|
+
# Ignore files already deleted
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def delete_prefixed(prefix)
|
55
|
+
instrument :delete_prefixed, prefix: prefix do
|
56
|
+
marker = nil
|
57
|
+
|
58
|
+
loop do
|
59
|
+
results = blobs.list_blobs(container, prefix: prefix, marker: marker)
|
60
|
+
|
61
|
+
results.each do |blob|
|
62
|
+
blobs.delete_blob(container, blob.name)
|
63
|
+
end
|
64
|
+
|
65
|
+
break unless marker = results.continuation_token.presence
|
50
66
|
end
|
51
67
|
end
|
52
68
|
end
|
53
69
|
|
54
70
|
def exist?(key)
|
55
|
-
instrument :exist, key do |payload|
|
71
|
+
instrument :exist, key: key do |payload|
|
56
72
|
answer = blob_for(key).present?
|
57
73
|
payload[:exist] = answer
|
58
74
|
answer
|
@@ -60,7 +76,7 @@ module ActiveStorage
|
|
60
76
|
end
|
61
77
|
|
62
78
|
def url(key, expires_in:, filename:, disposition:, content_type:)
|
63
|
-
instrument :url, key do |payload|
|
79
|
+
instrument :url, key: key do |payload|
|
64
80
|
base_url = url_for(key)
|
65
81
|
generated_url = signer.signed_uri(
|
66
82
|
URI(base_url), false,
|
@@ -77,7 +93,7 @@ module ActiveStorage
|
|
77
93
|
end
|
78
94
|
|
79
95
|
def url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:)
|
80
|
-
instrument :url, key do |payload|
|
96
|
+
instrument :url, key: key do |payload|
|
81
97
|
base_url = url_for(key)
|
82
98
|
generated_url = signer.signed_uri(URI(base_url), false, permissions: "rw",
|
83
99
|
expiry: format_expiry(expires_in)).to_s
|
@@ -9,14 +9,14 @@ module ActiveStorage
|
|
9
9
|
# Wraps a local disk path as an Active Storage service. See ActiveStorage::Service for the generic API
|
10
10
|
# documentation that applies to all services.
|
11
11
|
class Service::DiskService < Service
|
12
|
-
attr_reader :root
|
12
|
+
attr_reader :root, :host
|
13
13
|
|
14
|
-
def initialize(root:)
|
15
|
-
@root = root
|
14
|
+
def initialize(root:, host: "http://localhost:3000")
|
15
|
+
@root, @host = root, host
|
16
16
|
end
|
17
17
|
|
18
18
|
def upload(key, io, checksum: nil)
|
19
|
-
instrument :upload, key, checksum: checksum do
|
19
|
+
instrument :upload, key: key, checksum: checksum do
|
20
20
|
IO.copy_stream(io, make_path_for(key))
|
21
21
|
ensure_integrity_of(key, checksum) if checksum
|
22
22
|
end
|
@@ -24,7 +24,7 @@ module ActiveStorage
|
|
24
24
|
|
25
25
|
def download(key)
|
26
26
|
if block_given?
|
27
|
-
instrument :streaming_download, key do
|
27
|
+
instrument :streaming_download, key: key do
|
28
28
|
File.open(path_for(key), "rb") do |file|
|
29
29
|
while data = file.read(64.kilobytes)
|
30
30
|
yield data
|
@@ -32,14 +32,14 @@ module ActiveStorage
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
else
|
35
|
-
instrument :download, key do
|
35
|
+
instrument :download, key: key do
|
36
36
|
File.binread path_for(key)
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
41
|
def delete(key)
|
42
|
-
instrument :delete, key do
|
42
|
+
instrument :delete, key: key do
|
43
43
|
begin
|
44
44
|
File.delete path_for(key)
|
45
45
|
rescue Errno::ENOENT
|
@@ -48,8 +48,16 @@ module ActiveStorage
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
+
def delete_prefixed(prefix)
|
52
|
+
instrument :delete_prefixed, prefix: prefix do
|
53
|
+
Dir.glob(path_for("#{prefix}*")).each do |path|
|
54
|
+
FileUtils.rm_rf(path)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
51
59
|
def exist?(key)
|
52
|
-
instrument :exist, key do |payload|
|
60
|
+
instrument :exist, key: key do |payload|
|
53
61
|
answer = File.exist? path_for(key)
|
54
62
|
payload[:exist] = answer
|
55
63
|
answer
|
@@ -57,18 +65,17 @@ module ActiveStorage
|
|
57
65
|
end
|
58
66
|
|
59
67
|
def url(key, expires_in:, filename:, disposition:, content_type:)
|
60
|
-
instrument :url, key do |payload|
|
68
|
+
instrument :url, key: key do |payload|
|
61
69
|
verified_key_with_expiration = ActiveStorage.verifier.generate(key, expires_in: expires_in, purpose: :blob_key)
|
62
70
|
|
63
71
|
generated_url =
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
end
|
72
|
+
Rails.application.routes.url_helpers.rails_disk_service_url(
|
73
|
+
verified_key_with_expiration,
|
74
|
+
filename: filename,
|
75
|
+
disposition: content_disposition_with(type: disposition, filename: filename),
|
76
|
+
content_type: content_type,
|
77
|
+
host: host
|
78
|
+
)
|
72
79
|
|
73
80
|
payload[:url] = generated_url
|
74
81
|
|
@@ -77,7 +84,7 @@ module ActiveStorage
|
|
77
84
|
end
|
78
85
|
|
79
86
|
def url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:)
|
80
|
-
instrument :url, key do |payload|
|
87
|
+
instrument :url, key: key do |payload|
|
81
88
|
verified_token_with_expiration = ActiveStorage.verifier.generate(
|
82
89
|
{
|
83
90
|
key: key,
|
@@ -89,12 +96,7 @@ module ActiveStorage
|
|
89
96
|
purpose: :blob_token }
|
90
97
|
)
|
91
98
|
|
92
|
-
generated_url =
|
93
|
-
if defined?(Rails.application)
|
94
|
-
Rails.application.routes.url_helpers.update_rails_disk_service_path verified_token_with_expiration
|
95
|
-
else
|
96
|
-
"/rails/active_storage/disk/#{verified_token_with_expiration}"
|
97
|
-
end
|
99
|
+
generated_url = Rails.application.routes.url_helpers.update_rails_disk_service_url(verified_token_with_expiration, host: host)
|
98
100
|
|
99
101
|
payload[:url] = generated_url
|
100
102
|
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
gem "google-cloud-storage", "~> 1.8"
|
4
|
+
|
3
5
|
require "google/cloud/storage"
|
4
6
|
require "active_support/core_ext/object/to_query"
|
5
7
|
|
@@ -12,9 +14,15 @@ module ActiveStorage
|
|
12
14
|
end
|
13
15
|
|
14
16
|
def upload(key, io, checksum: nil)
|
15
|
-
instrument :upload, key, checksum: checksum do
|
17
|
+
instrument :upload, key: key, checksum: checksum do
|
16
18
|
begin
|
17
|
-
|
19
|
+
# The official GCS client library doesn't allow us to create a file with no Content-Type metadata.
|
20
|
+
# We need the file we create to have no Content-Type so we can control it via the response-content-type
|
21
|
+
# param in signed URLs. Workaround: let the GCS client create the file with an inferred
|
22
|
+
# Content-Type (usually "application/octet-stream") then clear it.
|
23
|
+
bucket.create_file(io, key, md5: checksum).update do |file|
|
24
|
+
file.content_type = nil
|
25
|
+
end
|
18
26
|
rescue Google::Cloud::InvalidArgumentError
|
19
27
|
raise ActiveStorage::IntegrityError
|
20
28
|
end
|
@@ -23,7 +31,7 @@ module ActiveStorage
|
|
23
31
|
|
24
32
|
# FIXME: Download in chunks when given a block.
|
25
33
|
def download(key)
|
26
|
-
instrument :download, key do
|
34
|
+
instrument :download, key: key do
|
27
35
|
io = file_for(key).download
|
28
36
|
io.rewind
|
29
37
|
|
@@ -36,7 +44,7 @@ module ActiveStorage
|
|
36
44
|
end
|
37
45
|
|
38
46
|
def delete(key)
|
39
|
-
instrument :delete, key do
|
47
|
+
instrument :delete, key: key do
|
40
48
|
begin
|
41
49
|
file_for(key).delete
|
42
50
|
rescue Google::Cloud::NotFoundError
|
@@ -45,8 +53,14 @@ module ActiveStorage
|
|
45
53
|
end
|
46
54
|
end
|
47
55
|
|
56
|
+
def delete_prefixed(prefix)
|
57
|
+
instrument :delete_prefixed, prefix: prefix do
|
58
|
+
bucket.files(prefix: prefix).all(&:delete)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
48
62
|
def exist?(key)
|
49
|
-
instrument :exist, key do |payload|
|
63
|
+
instrument :exist, key: key do |payload|
|
50
64
|
answer = file_for(key).exists?
|
51
65
|
payload[:exist] = answer
|
52
66
|
answer
|
@@ -54,7 +68,7 @@ module ActiveStorage
|
|
54
68
|
end
|
55
69
|
|
56
70
|
def url(key, expires_in:, filename:, content_type:, disposition:)
|
57
|
-
instrument :url, key do |payload|
|
71
|
+
instrument :url, key: key do |payload|
|
58
72
|
generated_url = file_for(key).signed_url expires: expires_in, query: {
|
59
73
|
"response-content-disposition" => content_disposition_with(type: disposition, filename: filename),
|
60
74
|
"response-content-type" => content_type
|
@@ -67,7 +81,7 @@ module ActiveStorage
|
|
67
81
|
end
|
68
82
|
|
69
83
|
def url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:)
|
70
|
-
instrument :url, key do |payload|
|
84
|
+
instrument :url, key: key do |payload|
|
71
85
|
generated_url = bucket.signed_url key, method: "PUT", expires: expires_in,
|
72
86
|
content_type: content_type, content_md5: checksum
|
73
87
|
|