activestorage 6.1.6.1 → 7.0.3.1
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 +4 -4
- data/CHANGELOG.md +180 -212
- data/README.md +25 -11
- data/app/assets/javascripts/activestorage.esm.js +844 -0
- data/app/assets/javascripts/activestorage.js +257 -376
- data/app/controllers/active_storage/base_controller.rb +0 -9
- data/app/controllers/active_storage/blobs/proxy_controller.rb +15 -4
- data/app/controllers/active_storage/blobs/redirect_controller.rb +6 -4
- data/app/controllers/active_storage/disk_controller.rb +1 -0
- data/app/controllers/active_storage/representations/base_controller.rb +5 -1
- data/app/controllers/active_storage/representations/proxy_controller.rb +7 -3
- data/app/controllers/active_storage/representations/redirect_controller.rb +6 -4
- data/app/controllers/concerns/active_storage/set_blob.rb +6 -2
- data/app/controllers/concerns/active_storage/set_current.rb +3 -3
- data/app/controllers/concerns/active_storage/streaming.rb +65 -0
- data/app/javascript/activestorage/ujs.js +1 -1
- data/app/models/active_storage/attachment.rb +35 -2
- data/app/models/active_storage/blob/representable.rb +7 -5
- data/app/models/active_storage/blob.rb +92 -36
- data/app/models/active_storage/current.rb +12 -2
- data/app/models/active_storage/preview.rb +6 -4
- data/app/models/active_storage/record.rb +1 -1
- data/app/models/active_storage/variant.rb +3 -6
- data/app/models/active_storage/variant_record.rb +2 -0
- data/app/models/active_storage/variant_with_record.rb +9 -5
- data/app/models/active_storage/variation.rb +2 -2
- data/config/routes.rb +10 -10
- data/db/migrate/20170806125915_create_active_storage_tables.rb +32 -11
- 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 +17 -2
- data/db/update_migrate/20211119233751_remove_not_null_on_active_storage_blobs_checksum.rb +7 -0
- data/lib/active_storage/analyzer/audio_analyzer.rb +65 -0
- data/lib/active_storage/analyzer/image_analyzer/image_magick.rb +39 -0
- data/lib/active_storage/analyzer/image_analyzer/vips.rb +49 -0
- data/lib/active_storage/analyzer/image_analyzer.rb +2 -30
- data/lib/active_storage/analyzer/video_analyzer.rb +27 -12
- data/lib/active_storage/analyzer.rb +8 -4
- data/lib/active_storage/attached/changes/create_many.rb +7 -3
- data/lib/active_storage/attached/changes/create_one.rb +1 -1
- data/lib/active_storage/attached/changes/create_one_of_many.rb +1 -1
- data/lib/active_storage/attached/changes/delete_many.rb +1 -1
- data/lib/active_storage/attached/changes/delete_one.rb +1 -1
- data/lib/active_storage/attached/changes/detach_many.rb +18 -0
- data/lib/active_storage/attached/changes/detach_one.rb +24 -0
- data/lib/active_storage/attached/changes/purge_many.rb +27 -0
- data/lib/active_storage/attached/changes/purge_one.rb +27 -0
- data/lib/active_storage/attached/changes.rb +7 -1
- data/lib/active_storage/attached/many.rb +27 -15
- data/lib/active_storage/attached/model.rb +35 -7
- data/lib/active_storage/attached/one.rb +32 -27
- data/lib/active_storage/downloader.rb +4 -4
- data/lib/active_storage/engine.rb +45 -1
- data/lib/active_storage/fixture_set.rb +76 -0
- data/lib/active_storage/gem_version.rb +4 -4
- data/lib/active_storage/previewer.rb +4 -4
- data/lib/active_storage/reflection.rb +12 -2
- data/lib/active_storage/service/azure_storage_service.rb +28 -6
- data/lib/active_storage/service/configurator.rb +1 -1
- data/lib/active_storage/service/disk_service.rb +24 -19
- data/lib/active_storage/service/gcs_service.rb +109 -11
- data/lib/active_storage/service/mirror_service.rb +2 -2
- data/lib/active_storage/service/registry.rb +1 -1
- data/lib/active_storage/service/s3_service.rb +37 -15
- data/lib/active_storage/service.rb +13 -5
- data/lib/active_storage/transformers/image_processing_transformer.rb +1 -1
- data/lib/active_storage/transformers/transformer.rb +1 -1
- data/lib/active_storage/version.rb +1 -1
- data/lib/active_storage.rb +4 -0
- metadata +24 -14
- data/app/controllers/concerns/active_storage/set_headers.rb +0 -12
@@ -1,12 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveStorage
|
4
|
-
class Attached::Changes::CreateMany
|
4
|
+
class Attached::Changes::CreateMany # :nodoc:
|
5
5
|
attr_reader :name, :record, :attachables
|
6
6
|
|
7
7
|
def initialize(name, record, attachables)
|
8
8
|
@name, @record, @attachables = name, record, Array(attachables)
|
9
9
|
blobs.each(&:identify_without_saving)
|
10
|
+
attachments
|
10
11
|
end
|
11
12
|
|
12
13
|
def attachments
|
@@ -35,13 +36,16 @@ module ActiveStorage
|
|
35
36
|
ActiveStorage::Attached::Changes::CreateOneOfMany.new(name, record, attachable)
|
36
37
|
end
|
37
38
|
|
38
|
-
|
39
39
|
def assign_associated_attachments
|
40
|
-
record.public_send("#{name}_attachments=",
|
40
|
+
record.public_send("#{name}_attachments=", persisted_or_new_attachments)
|
41
41
|
end
|
42
42
|
|
43
43
|
def reset_associated_blobs
|
44
44
|
record.public_send("#{name}_blobs").reset
|
45
45
|
end
|
46
|
+
|
47
|
+
def persisted_or_new_attachments
|
48
|
+
attachments.select { |attachment| attachment.persisted? || attachment.new_record? }
|
49
|
+
end
|
46
50
|
end
|
47
51
|
end
|
@@ -4,7 +4,7 @@ require "action_dispatch"
|
|
4
4
|
require "action_dispatch/http/upload"
|
5
5
|
|
6
6
|
module ActiveStorage
|
7
|
-
class Attached::Changes::CreateOne
|
7
|
+
class Attached::Changes::CreateOne # :nodoc:
|
8
8
|
attr_reader :name, :record, :attachable
|
9
9
|
|
10
10
|
def initialize(name, record, attachable)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveStorage
|
4
|
-
class Attached::Changes::CreateOneOfMany < Attached::Changes::CreateOne
|
4
|
+
class Attached::Changes::CreateOneOfMany < Attached::Changes::CreateOne # :nodoc:
|
5
5
|
private
|
6
6
|
def find_attachment
|
7
7
|
record.public_send("#{name}_attachments").detect { |attachment| attachment.blob_id == blob.id }
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveStorage
|
4
|
+
class Attached::Changes::DetachMany # :nodoc:
|
5
|
+
attr_reader :name, :record, :attachments
|
6
|
+
|
7
|
+
def initialize(name, record, attachments)
|
8
|
+
@name, @record, @attachments = name, record, attachments
|
9
|
+
end
|
10
|
+
|
11
|
+
def detach
|
12
|
+
if attachments.any?
|
13
|
+
attachments.delete_all if attachments.respond_to?(:delete_all)
|
14
|
+
record.attachment_changes.delete(name)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveStorage
|
4
|
+
class Attached::Changes::DetachOne # :nodoc:
|
5
|
+
attr_reader :name, :record, :attachment
|
6
|
+
|
7
|
+
def initialize(name, record, attachment)
|
8
|
+
@name, @record, @attachment = name, record, attachment
|
9
|
+
end
|
10
|
+
|
11
|
+
def detach
|
12
|
+
if attachment.present?
|
13
|
+
attachment.delete
|
14
|
+
reset
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def reset
|
20
|
+
record.attachment_changes.delete(name)
|
21
|
+
record.public_send("#{name}_attachment=", nil)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveStorage
|
4
|
+
class Attached::Changes::PurgeMany # :nodoc:
|
5
|
+
attr_reader :name, :record, :attachments
|
6
|
+
|
7
|
+
def initialize(name, record, attachments)
|
8
|
+
@name, @record, @attachments = name, record, attachments
|
9
|
+
end
|
10
|
+
|
11
|
+
def purge
|
12
|
+
attachments.each(&:purge)
|
13
|
+
reset
|
14
|
+
end
|
15
|
+
|
16
|
+
def purge_later
|
17
|
+
attachments.each(&:purge_later)
|
18
|
+
reset
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def reset
|
23
|
+
record.attachment_changes.delete(name)
|
24
|
+
record.public_send("#{name}_attachments").reset
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveStorage
|
4
|
+
class Attached::Changes::PurgeOne # :nodoc:
|
5
|
+
attr_reader :name, :record, :attachment
|
6
|
+
|
7
|
+
def initialize(name, record, attachment)
|
8
|
+
@name, @record, @attachment = name, record, attachment
|
9
|
+
end
|
10
|
+
|
11
|
+
def purge
|
12
|
+
attachment&.purge
|
13
|
+
reset
|
14
|
+
end
|
15
|
+
|
16
|
+
def purge_later
|
17
|
+
attachment&.purge_later
|
18
|
+
reset
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def reset
|
23
|
+
record.attachment_changes.delete(name)
|
24
|
+
record.public_send("#{name}_attachment=", nil)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveStorage
|
4
|
-
module Attached::Changes
|
4
|
+
module Attached::Changes # :nodoc:
|
5
5
|
extend ActiveSupport::Autoload
|
6
6
|
|
7
7
|
eager_autoload do
|
@@ -11,6 +11,12 @@ module ActiveStorage
|
|
11
11
|
|
12
12
|
autoload :DeleteOne
|
13
13
|
autoload :DeleteMany
|
14
|
+
|
15
|
+
autoload :DetachOne
|
16
|
+
autoload :DetachMany
|
17
|
+
|
18
|
+
autoload :PurgeOne
|
19
|
+
autoload :PurgeMany
|
14
20
|
end
|
15
21
|
end
|
16
22
|
end
|
@@ -3,6 +3,25 @@
|
|
3
3
|
module ActiveStorage
|
4
4
|
# Decorated proxy object representing of multiple attachments to a model.
|
5
5
|
class Attached::Many < Attached
|
6
|
+
##
|
7
|
+
# :method: purge
|
8
|
+
#
|
9
|
+
# Directly purges each associated attachment (i.e. destroys the blobs and
|
10
|
+
# attachments and deletes the files on the service).
|
11
|
+
delegate :purge, to: :purge_many
|
12
|
+
|
13
|
+
##
|
14
|
+
# :method: purge_later
|
15
|
+
#
|
16
|
+
# Purges each associated attachment through the queuing system.
|
17
|
+
delegate :purge_later, to: :purge_many
|
18
|
+
|
19
|
+
##
|
20
|
+
# :method: detach
|
21
|
+
#
|
22
|
+
# Deletes associated attachments without purging them, leaving their respective blobs in place.
|
23
|
+
delegate :detach, to: :detach_many
|
24
|
+
|
6
25
|
delegate_missing_to :attachments
|
7
26
|
|
8
27
|
# Returns all the associated attachment records.
|
@@ -25,7 +44,7 @@ module ActiveStorage
|
|
25
44
|
#
|
26
45
|
# document.images.attach(params[:images]) # Array of ActionDispatch::Http::UploadedFile objects
|
27
46
|
# document.images.attach(params[:signed_blob_id]) # Signed reference to blob from direct upload
|
28
|
-
# document.images.attach(io: File.open("/path/to/racecar.jpg"), filename: "racecar.jpg", content_type: "image/
|
47
|
+
# document.images.attach(io: File.open("/path/to/racecar.jpg"), filename: "racecar.jpg", content_type: "image/jpeg")
|
29
48
|
# document.images.attach([ first_blob, second_blob ])
|
30
49
|
def attach(*attachables)
|
31
50
|
if record.persisted? && !record.changed?
|
@@ -47,20 +66,13 @@ module ActiveStorage
|
|
47
66
|
attachments.any?
|
48
67
|
end
|
49
68
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
##
|
56
|
-
# :method: purge
|
57
|
-
#
|
58
|
-
# Directly purges each associated attachment (i.e. destroys the blobs and
|
59
|
-
# attachments and deletes the files on the service).
|
69
|
+
private
|
70
|
+
def purge_many
|
71
|
+
Attached::Changes::PurgeMany.new(name, record, attachments)
|
72
|
+
end
|
60
73
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
# Purges each associated attachment through the queuing system.
|
74
|
+
def detach_many
|
75
|
+
Attached::Changes::DetachMany.new(name, record, attachments)
|
76
|
+
end
|
65
77
|
end
|
66
78
|
end
|
@@ -83,6 +83,7 @@ module ActiveStorage
|
|
83
83
|
{ dependent: dependent, service_name: service },
|
84
84
|
self
|
85
85
|
)
|
86
|
+
yield reflection if block_given?
|
86
87
|
ActiveRecord::Reflection.add_attachment_reflection(self, name, reflection)
|
87
88
|
end
|
88
89
|
|
@@ -136,15 +137,23 @@ module ActiveStorage
|
|
136
137
|
end
|
137
138
|
|
138
139
|
def #{name}=(attachables)
|
140
|
+
attachables = Array(attachables).compact_blank
|
141
|
+
|
139
142
|
if ActiveStorage.replace_on_assign_to_many
|
140
143
|
attachment_changes["#{name}"] =
|
141
|
-
if
|
144
|
+
if attachables.none?
|
142
145
|
ActiveStorage::Attached::Changes::DeleteMany.new("#{name}", self)
|
143
146
|
else
|
144
147
|
ActiveStorage::Attached::Changes::CreateMany.new("#{name}", self, attachables)
|
145
148
|
end
|
146
149
|
else
|
147
|
-
|
150
|
+
ActiveSupport::Deprecation.warn \
|
151
|
+
"config.active_storage.replace_on_assign_to_many is deprecated and will be removed in Rails 7.1. " \
|
152
|
+
"Make sure that your code works well with config.active_storage.replace_on_assign_to_many set to true before upgrading. " \
|
153
|
+
"To append new attachables to the Active Storage association, prefer using `attach`. " \
|
154
|
+
"Using association setter would result in purging the existing attached attachments and replacing them with new ones."
|
155
|
+
|
156
|
+
if attachables.any?
|
148
157
|
attachment_changes["#{name}"] =
|
149
158
|
ActiveStorage::Attached::Changes::CreateMany.new("#{name}", self, #{name}.blobs + attachables)
|
150
159
|
end
|
@@ -154,18 +163,36 @@ module ActiveStorage
|
|
154
163
|
|
155
164
|
has_many :"#{name}_attachments", -> { where(name: name) }, as: :record, class_name: "ActiveStorage::Attachment", inverse_of: :record, dependent: :destroy, strict_loading: strict_loading do
|
156
165
|
def purge
|
166
|
+
deprecate(:purge)
|
157
167
|
each(&:purge)
|
158
168
|
reset
|
159
169
|
end
|
160
170
|
|
161
171
|
def purge_later
|
172
|
+
deprecate(:purge_later)
|
162
173
|
each(&:purge_later)
|
163
174
|
reset
|
164
175
|
end
|
176
|
+
|
177
|
+
private
|
178
|
+
def deprecate(action)
|
179
|
+
reflection_name = proxy_association.reflection.name
|
180
|
+
attached_name = reflection_name.to_s.partition("_").first
|
181
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
182
|
+
Calling `#{action}` from `#{reflection_name}` is deprecated and will be removed in Rails 7.1.
|
183
|
+
To migrate to Rails 7.1's behavior call `#{action}` from `#{attached_name}` instead: `#{attached_name}.#{action}`.
|
184
|
+
MSG
|
185
|
+
end
|
165
186
|
end
|
166
187
|
has_many :"#{name}_blobs", through: :"#{name}_attachments", class_name: "ActiveStorage::Blob", source: :blob, strict_loading: strict_loading
|
167
188
|
|
168
|
-
scope :"with_attached_#{name}", -> {
|
189
|
+
scope :"with_attached_#{name}", -> {
|
190
|
+
if ActiveStorage.track_variants
|
191
|
+
includes("#{name}_attachments": { blob: :variant_records })
|
192
|
+
else
|
193
|
+
includes("#{name}_attachments": :blob)
|
194
|
+
end
|
195
|
+
}
|
169
196
|
|
170
197
|
after_save { attachment_changes[name.to_s]&.save }
|
171
198
|
|
@@ -178,6 +205,7 @@ module ActiveStorage
|
|
178
205
|
{ dependent: dependent, service_name: service },
|
179
206
|
self
|
180
207
|
)
|
208
|
+
yield reflection if block_given?
|
181
209
|
ActiveRecord::Reflection.add_attachment_reflection(self, name, reflection)
|
182
210
|
end
|
183
211
|
|
@@ -191,21 +219,21 @@ module ActiveStorage
|
|
191
219
|
end
|
192
220
|
end
|
193
221
|
|
194
|
-
def attachment_changes
|
222
|
+
def attachment_changes # :nodoc:
|
195
223
|
@attachment_changes ||= {}
|
196
224
|
end
|
197
225
|
|
198
|
-
def changed_for_autosave?
|
226
|
+
def changed_for_autosave? # :nodoc:
|
199
227
|
super || attachment_changes.any?
|
200
228
|
end
|
201
229
|
|
202
|
-
def initialize_dup(*)
|
230
|
+
def initialize_dup(*) # :nodoc:
|
203
231
|
super
|
204
232
|
@active_storage_attached = nil
|
205
233
|
@attachment_changes = nil
|
206
234
|
end
|
207
235
|
|
208
|
-
def reload(*)
|
236
|
+
def reload(*) # :nodoc:
|
209
237
|
super.tap { @attachment_changes = nil }
|
210
238
|
end
|
211
239
|
end
|
@@ -3,6 +3,25 @@
|
|
3
3
|
module ActiveStorage
|
4
4
|
# Representation of a single attachment to a model.
|
5
5
|
class Attached::One < Attached
|
6
|
+
##
|
7
|
+
# :method: purge
|
8
|
+
#
|
9
|
+
# Directly purges the attachment (i.e. destroys the blob and
|
10
|
+
# attachment and deletes the file on the service).
|
11
|
+
delegate :purge, to: :purge_one
|
12
|
+
|
13
|
+
##
|
14
|
+
# :method: purge_later
|
15
|
+
#
|
16
|
+
# Purges the attachment through the queuing system.
|
17
|
+
delegate :purge_later, to: :purge_one
|
18
|
+
|
19
|
+
##
|
20
|
+
# :method: detach
|
21
|
+
#
|
22
|
+
# Deletes the attachment without purging it, leaving its blob in place.
|
23
|
+
delegate :detach, to: :detach_one
|
24
|
+
|
6
25
|
delegate_missing_to :attachment, allow_nil: true
|
7
26
|
|
8
27
|
# Returns the associated attachment record.
|
@@ -13,6 +32,13 @@ module ActiveStorage
|
|
13
32
|
change.present? ? change.attachment : record.public_send("#{name}_attachment")
|
14
33
|
end
|
15
34
|
|
35
|
+
# Returns +true+ if an attachment is not attached.
|
36
|
+
#
|
37
|
+
# class User < ApplicationRecord
|
38
|
+
# has_one_attached :avatar
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# User.new.avatar.blank? # => true
|
16
42
|
def blank?
|
17
43
|
!attached?
|
18
44
|
end
|
@@ -25,7 +51,7 @@ module ActiveStorage
|
|
25
51
|
#
|
26
52
|
# person.avatar.attach(params[:avatar]) # ActionDispatch::Http::UploadedFile object
|
27
53
|
# person.avatar.attach(params[:signed_blob_id]) # Signed reference to blob from direct upload
|
28
|
-
# person.avatar.attach(io: File.open("/path/to/face.jpg"), filename: "face.jpg", content_type: "image/
|
54
|
+
# person.avatar.attach(io: File.open("/path/to/face.jpg"), filename: "face.jpg", content_type: "image/jpeg")
|
29
55
|
# person.avatar.attach(avatar_blob) # ActiveStorage::Blob object
|
30
56
|
def attach(attachable)
|
31
57
|
if record.persisted? && !record.changed?
|
@@ -47,34 +73,13 @@ module ActiveStorage
|
|
47
73
|
attachment.present?
|
48
74
|
end
|
49
75
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
attachment.delete
|
54
|
-
write_attachment nil
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
# Directly purges the attachment (i.e. destroys the blob and
|
59
|
-
# attachment and deletes the file on the service).
|
60
|
-
def purge
|
61
|
-
if attached?
|
62
|
-
attachment.purge
|
63
|
-
write_attachment nil
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
# Purges the attachment through the queuing system.
|
68
|
-
def purge_later
|
69
|
-
if attached?
|
70
|
-
attachment.purge_later
|
71
|
-
write_attachment nil
|
76
|
+
private
|
77
|
+
def purge_one
|
78
|
+
Attached::Changes::PurgeOne.new(name, record, attachment)
|
72
79
|
end
|
73
|
-
end
|
74
80
|
|
75
|
-
|
76
|
-
|
77
|
-
record.public_send("#{name}_attachment=", attachment)
|
81
|
+
def detach_one
|
82
|
+
Attached::Changes::DetachOne.new(name, record, attachment)
|
78
83
|
end
|
79
84
|
end
|
80
85
|
end
|
@@ -1,17 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveStorage
|
4
|
-
class Downloader
|
4
|
+
class Downloader # :nodoc:
|
5
5
|
attr_reader :service
|
6
6
|
|
7
7
|
def initialize(service)
|
8
8
|
@service = service
|
9
9
|
end
|
10
10
|
|
11
|
-
def open(key, checksum
|
11
|
+
def open(key, checksum: nil, verify: true, name: "ActiveStorage-", tmpdir: nil)
|
12
12
|
open_tempfile(name, tmpdir) do |file|
|
13
13
|
download key, file
|
14
|
-
verify_integrity_of
|
14
|
+
verify_integrity_of(file, checksum: checksum) if verify
|
15
15
|
yield file
|
16
16
|
end
|
17
17
|
end
|
@@ -35,7 +35,7 @@ module ActiveStorage
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def verify_integrity_of(file, checksum:)
|
38
|
-
unless Digest::MD5.file(file).base64digest == checksum
|
38
|
+
unless OpenSSL::Digest::MD5.file(file).base64digest == checksum
|
39
39
|
raise ActiveStorage::IntegrityError
|
40
40
|
end
|
41
41
|
end
|
@@ -12,7 +12,10 @@ require "active_storage/previewer/mupdf_previewer"
|
|
12
12
|
require "active_storage/previewer/video_previewer"
|
13
13
|
|
14
14
|
require "active_storage/analyzer/image_analyzer"
|
15
|
+
require "active_storage/analyzer/image_analyzer/image_magick"
|
16
|
+
require "active_storage/analyzer/image_analyzer/vips"
|
15
17
|
require "active_storage/analyzer/video_analyzer"
|
18
|
+
require "active_storage/analyzer/audio_analyzer"
|
16
19
|
|
17
20
|
require "active_storage/service/registry"
|
18
21
|
|
@@ -24,9 +27,10 @@ module ActiveStorage
|
|
24
27
|
|
25
28
|
config.active_storage = ActiveSupport::OrderedOptions.new
|
26
29
|
config.active_storage.previewers = [ ActiveStorage::Previewer::PopplerPDFPreviewer, ActiveStorage::Previewer::MuPDFPreviewer, ActiveStorage::Previewer::VideoPreviewer ]
|
27
|
-
config.active_storage.analyzers = [ ActiveStorage::Analyzer::ImageAnalyzer, ActiveStorage::Analyzer::VideoAnalyzer ]
|
30
|
+
config.active_storage.analyzers = [ ActiveStorage::Analyzer::ImageAnalyzer::Vips, ActiveStorage::Analyzer::ImageAnalyzer::ImageMagick, ActiveStorage::Analyzer::VideoAnalyzer, ActiveStorage::Analyzer::AudioAnalyzer ]
|
28
31
|
config.active_storage.paths = ActiveSupport::OrderedOptions.new
|
29
32
|
config.active_storage.queues = ActiveSupport::InheritableOptions.new
|
33
|
+
config.active_storage.precompile_assets = true
|
30
34
|
|
31
35
|
config.active_storage.variable_content_types = %w(
|
32
36
|
image/png
|
@@ -39,6 +43,9 @@ module ActiveStorage
|
|
39
43
|
image/vnd.adobe.photoshop
|
40
44
|
image/vnd.microsoft.icon
|
41
45
|
image/webp
|
46
|
+
image/avif
|
47
|
+
image/heic
|
48
|
+
image/heif
|
42
49
|
)
|
43
50
|
|
44
51
|
config.active_storage.web_image_content_types = %w(
|
@@ -105,10 +112,13 @@ module ActiveStorage
|
|
105
112
|
ActiveStorage.web_image_content_types = app.config.active_storage.web_image_content_types || []
|
106
113
|
ActiveStorage.content_types_to_serve_as_binary = app.config.active_storage.content_types_to_serve_as_binary || []
|
107
114
|
ActiveStorage.service_urls_expire_in = app.config.active_storage.service_urls_expire_in || 5.minutes
|
115
|
+
ActiveStorage.urls_expire_in = app.config.active_storage.urls_expire_in
|
108
116
|
ActiveStorage.content_types_allowed_inline = app.config.active_storage.content_types_allowed_inline || []
|
109
117
|
ActiveStorage.binary_content_type = app.config.active_storage.binary_content_type || "application/octet-stream"
|
110
118
|
ActiveStorage.video_preview_arguments = app.config.active_storage.video_preview_arguments || "-y -vframes 1 -f image2"
|
111
119
|
|
120
|
+
ActiveStorage.silence_invalid_content_types_warning = app.config.active_storage.silence_invalid_content_types_warning || false
|
121
|
+
|
112
122
|
ActiveStorage.replace_on_assign_to_many = app.config.active_storage.replace_on_assign_to_many || false
|
113
123
|
ActiveStorage.track_variants = app.config.active_storage.track_variants || false
|
114
124
|
end
|
@@ -159,5 +169,39 @@ module ActiveStorage
|
|
159
169
|
ActiveRecord::Reflection.singleton_class.prepend(Reflection::ReflectionExtension)
|
160
170
|
end
|
161
171
|
end
|
172
|
+
|
173
|
+
initializer "action_view.configuration" do
|
174
|
+
config.after_initialize do |app|
|
175
|
+
ActiveSupport.on_load(:action_view) do
|
176
|
+
multiple_file_field_include_hidden = app.config.active_storage.delete(:multiple_file_field_include_hidden)
|
177
|
+
|
178
|
+
unless multiple_file_field_include_hidden.nil?
|
179
|
+
ActionView::Helpers::FormHelper.multiple_file_field_include_hidden = multiple_file_field_include_hidden
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
initializer "active_storage.asset" do
|
186
|
+
config.after_initialize do |app|
|
187
|
+
if app.config.respond_to?(:assets) && app.config.active_storage.precompile_assets
|
188
|
+
app.config.assets.precompile += %w( activestorage activestorage.esm )
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
initializer "active_storage.fixture_set" do
|
194
|
+
ActiveSupport.on_load(:active_record_fixture_set) do
|
195
|
+
ActiveStorage::FixtureSet.file_fixture_path ||= Rails.root.join(*[
|
196
|
+
ENV.fetch("FIXTURES_PATH") { File.join("test", "fixtures") },
|
197
|
+
ENV["FIXTURES_DIR"],
|
198
|
+
"files"
|
199
|
+
].compact_blank)
|
200
|
+
end
|
201
|
+
|
202
|
+
ActiveSupport.on_load(:active_support_test_case) do
|
203
|
+
ActiveStorage::FixtureSet.file_fixture_path = ActiveSupport::TestCase.file_fixture_path
|
204
|
+
end
|
205
|
+
end
|
162
206
|
end
|
163
207
|
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/testing/file_fixtures"
|
4
|
+
require "active_record/secure_token"
|
5
|
+
|
6
|
+
module ActiveStorage
|
7
|
+
# Fixtures are a way of organizing data that you want to test against; in
|
8
|
+
# short, sample data.
|
9
|
+
#
|
10
|
+
# To learn more about fixtures, read the
|
11
|
+
# {ActiveRecord::FixtureSet}[rdoc-ref:ActiveRecord::FixtureSet] documentation.
|
12
|
+
#
|
13
|
+
# === YAML
|
14
|
+
#
|
15
|
+
# Like other Active Record-backed models,
|
16
|
+
# {ActiveStorage::Attachment}[rdoc-ref:ActiveStorage::Attachment] and
|
17
|
+
# {ActiveStorage::Blob}[rdoc-ref:ActiveStorage::Blob] records inherit from
|
18
|
+
# {ActiveRecord::Base}[rdoc-ref:ActiveRecord::Base] instances and therefore
|
19
|
+
# can be populated by fixtures.
|
20
|
+
#
|
21
|
+
# Consider a hypothetical <tt>Article</tt> model class, its related
|
22
|
+
# fixture data, as well as fixture data for related ActiveStorage::Attachment
|
23
|
+
# and ActiveStorage::Blob records:
|
24
|
+
#
|
25
|
+
# # app/models/article.rb
|
26
|
+
# class Article < ApplicationRecord
|
27
|
+
# has_one_attached :thumbnail
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# # fixtures/active_storage/blobs.yml
|
31
|
+
# first_thumbnail_blob: <%= ActiveStorage::FixtureSet.blob filename: "first.png" %>
|
32
|
+
#
|
33
|
+
# # fixtures/active_storage/attachments.yml
|
34
|
+
# first_thumbnail_attachment:
|
35
|
+
# name: thumbnail
|
36
|
+
# record: first (Article)
|
37
|
+
# blob: first_thumbnail_blob
|
38
|
+
#
|
39
|
+
# When processed, Active Record will insert database records for each fixture
|
40
|
+
# entry and will ensure the Active Storage relationship is intact.
|
41
|
+
class FixtureSet
|
42
|
+
include ActiveSupport::Testing::FileFixtures
|
43
|
+
include ActiveRecord::SecureToken
|
44
|
+
|
45
|
+
# Generate a YAML-encoded representation of an ActiveStorage::Blob
|
46
|
+
# instance's attributes, resolve the file relative to the directory mentioned
|
47
|
+
# by <tt>ActiveSupport::Testing::FileFixtures.file_fixture</tt>, and upload
|
48
|
+
# the file to the Service
|
49
|
+
#
|
50
|
+
# === Examples
|
51
|
+
#
|
52
|
+
# # tests/fixtures/action_text/blobs.yml
|
53
|
+
# second_thumbnail_blob: <%= ActiveStorage::FixtureSet.blob(
|
54
|
+
# filename: "second.svg",
|
55
|
+
# ) %>
|
56
|
+
#
|
57
|
+
# third_thumbnail_blob: <%= ActiveStorage::FixtureSet.blob(
|
58
|
+
# filename: "third.svg",
|
59
|
+
# content_type: "image/svg+xml",
|
60
|
+
# service_name: "public"
|
61
|
+
# ) %>
|
62
|
+
#
|
63
|
+
def self.blob(filename:, **attributes)
|
64
|
+
new.prepare Blob.new(filename: filename, key: generate_unique_secure_token), **attributes
|
65
|
+
end
|
66
|
+
|
67
|
+
def prepare(instance, **attributes)
|
68
|
+
io = file_fixture(instance.filename.to_s).open
|
69
|
+
instance.unfurl(io)
|
70
|
+
instance.assign_attributes(attributes)
|
71
|
+
instance.upload_without_unfurling(io)
|
72
|
+
|
73
|
+
instance.attributes.transform_values { |value| value.is_a?(Hash) ? value.to_json : value }.compact.to_json
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -1,15 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveStorage
|
4
|
-
# Returns the version of
|
4
|
+
# Returns the currently loaded version of Active Storage as a <tt>Gem::Version</tt>.
|
5
5
|
def self.gem_version
|
6
6
|
Gem::Version.new VERSION::STRING
|
7
7
|
end
|
8
8
|
|
9
9
|
module VERSION
|
10
|
-
MAJOR =
|
11
|
-
MINOR =
|
12
|
-
TINY =
|
10
|
+
MAJOR = 7
|
11
|
+
MINOR = 0
|
12
|
+
TINY = 3
|
13
13
|
PRE = "1"
|
14
14
|
|
15
15
|
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
|