activestorage 6.1.7 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +152 -276
- data/MIT-LICENSE +1 -1
- data/README.md +29 -15
- data/app/assets/javascripts/activestorage.esm.js +848 -0
- data/app/assets/javascripts/activestorage.js +263 -376
- data/app/controllers/active_storage/base_controller.rb +0 -9
- data/app/controllers/active_storage/blobs/proxy_controller.rb +16 -4
- data/app/controllers/active_storage/blobs/redirect_controller.rb +6 -4
- data/app/controllers/active_storage/disk_controller.rb +5 -2
- data/app/controllers/active_storage/representations/base_controller.rb +5 -1
- data/app/controllers/active_storage/representations/proxy_controller.rb +8 -3
- data/app/controllers/active_storage/representations/redirect_controller.rb +6 -4
- data/app/controllers/concerns/active_storage/disable_session.rb +12 -0
- data/app/controllers/concerns/active_storage/file_server.rb +4 -1
- data/app/controllers/concerns/active_storage/set_blob.rb +6 -2
- data/app/controllers/concerns/active_storage/set_current.rb +3 -3
- data/app/controllers/concerns/active_storage/streaming.rb +66 -0
- data/app/javascript/activestorage/blob_record.js +4 -1
- data/app/javascript/activestorage/direct_upload.js +3 -2
- data/app/javascript/activestorage/index.js +3 -1
- data/app/javascript/activestorage/ujs.js +1 -1
- data/app/jobs/active_storage/analyze_job.rb +1 -1
- data/app/jobs/active_storage/mirror_job.rb +1 -1
- data/app/jobs/active_storage/purge_job.rb +1 -1
- data/app/jobs/active_storage/transform_job.rb +12 -0
- data/app/models/active_storage/attachment.rb +111 -4
- data/app/models/active_storage/blob/analyzable.rb +4 -3
- data/app/models/active_storage/blob/identifiable.rb +1 -0
- data/app/models/active_storage/blob/representable.rb +14 -8
- data/app/models/active_storage/blob.rb +93 -57
- data/app/models/active_storage/current.rb +2 -2
- data/app/models/active_storage/filename.rb +2 -0
- data/app/models/active_storage/named_variant.rb +21 -0
- data/app/models/active_storage/preview.rb +11 -7
- data/app/models/active_storage/record.rb +1 -1
- data/app/models/active_storage/variant.rb +10 -12
- data/app/models/active_storage/variant_record.rb +2 -0
- data/app/models/active_storage/variant_with_record.rb +28 -12
- data/app/models/active_storage/variation.rb +7 -5
- data/config/routes.rb +12 -10
- data/db/migrate/20170806125915_create_active_storage_tables.rb +15 -6
- data/db/update_migrate/20211119233751_remove_not_null_on_active_storage_blobs_checksum.rb +7 -0
- data/lib/active_storage/analyzer/audio_analyzer.rb +77 -0
- data/lib/active_storage/analyzer/image_analyzer/image_magick.rb +41 -0
- data/lib/active_storage/analyzer/image_analyzer/vips.rb +51 -0
- data/lib/active_storage/analyzer/image_analyzer.rb +4 -30
- data/lib/active_storage/analyzer/video_analyzer.rb +41 -17
- data/lib/active_storage/analyzer.rb +10 -4
- data/lib/active_storage/attached/changes/create_many.rb +14 -5
- data/lib/active_storage/attached/changes/create_one.rb +46 -4
- 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 +32 -19
- data/lib/active_storage/attached/model.rb +80 -29
- data/lib/active_storage/attached/one.rb +37 -31
- data/lib/active_storage/attached.rb +2 -0
- data/lib/active_storage/deprecator.rb +7 -0
- data/lib/active_storage/downloader.rb +4 -4
- data/lib/active_storage/engine.rb +55 -7
- data/lib/active_storage/fixture_set.rb +75 -0
- data/lib/active_storage/gem_version.rb +3 -3
- data/lib/active_storage/log_subscriber.rb +12 -0
- data/lib/active_storage/previewer.rb +12 -5
- data/lib/active_storage/reflection.rb +12 -2
- data/lib/active_storage/service/azure_storage_service.rb +30 -6
- data/lib/active_storage/service/configurator.rb +1 -1
- data/lib/active_storage/service/disk_service.rb +26 -19
- data/lib/active_storage/service/gcs_service.rb +100 -11
- data/lib/active_storage/service/mirror_service.rb +12 -7
- data/lib/active_storage/service/registry.rb +1 -1
- data/lib/active_storage/service/s3_service.rb +39 -15
- data/lib/active_storage/service.rb +17 -7
- data/lib/active_storage/transformers/image_processing_transformer.rb +1 -1
- data/lib/active_storage/transformers/transformer.rb +3 -1
- data/lib/active_storage/version.rb +1 -1
- data/lib/active_storage.rb +22 -2
- metadata +30 -30
- data/app/controllers/concerns/active_storage/set_headers.rb +0 -12
@@ -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
|
@@ -1,8 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveStorage
|
4
|
+
# = Active Storage \Attached \Many
|
5
|
+
#
|
4
6
|
# Decorated proxy object representing of multiple attachments to a model.
|
5
7
|
class Attached::Many < Attached
|
8
|
+
##
|
9
|
+
# :method: purge
|
10
|
+
#
|
11
|
+
# Directly purges each associated attachment (i.e. destroys the blobs and
|
12
|
+
# attachments and deletes the files on the service).
|
13
|
+
delegate :purge, to: :purge_many
|
14
|
+
|
15
|
+
##
|
16
|
+
# :method: purge_later
|
17
|
+
#
|
18
|
+
# Purges each associated attachment through the queuing system.
|
19
|
+
delegate :purge_later, to: :purge_many
|
20
|
+
|
21
|
+
##
|
22
|
+
# :method: detach
|
23
|
+
#
|
24
|
+
# Deletes associated attachments without purging them, leaving their respective blobs in place.
|
25
|
+
delegate :detach, to: :detach_many
|
26
|
+
|
6
27
|
delegate_missing_to :attachments
|
7
28
|
|
8
29
|
# Returns all the associated attachment records.
|
@@ -25,15 +46,14 @@ module ActiveStorage
|
|
25
46
|
#
|
26
47
|
# document.images.attach(params[:images]) # Array of ActionDispatch::Http::UploadedFile objects
|
27
48
|
# 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/
|
49
|
+
# document.images.attach(io: File.open("/path/to/racecar.jpg"), filename: "racecar.jpg", content_type: "image/jpeg")
|
29
50
|
# document.images.attach([ first_blob, second_blob ])
|
30
51
|
def attach(*attachables)
|
52
|
+
record.public_send("#{name}=", blobs + attachables.flatten)
|
31
53
|
if record.persisted? && !record.changed?
|
32
|
-
|
33
|
-
record.save
|
34
|
-
else
|
35
|
-
record.public_send("#{name}=", (change&.attachables || blobs) + attachables.flatten)
|
54
|
+
return if !record.save
|
36
55
|
end
|
56
|
+
record.public_send("#{name}")
|
37
57
|
end
|
38
58
|
|
39
59
|
# Returns true if any attachments have been made.
|
@@ -47,20 +67,13 @@ module ActiveStorage
|
|
47
67
|
attachments.any?
|
48
68
|
end
|
49
69
|
|
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).
|
70
|
+
private
|
71
|
+
def purge_many
|
72
|
+
Attached::Changes::PurgeMany.new(name, record, attachments)
|
73
|
+
end
|
60
74
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
# Purges each associated attachment through the queuing system.
|
75
|
+
def detach_many
|
76
|
+
Attached::Changes::DetachMany.new(name, record, attachments)
|
77
|
+
end
|
65
78
|
end
|
66
79
|
end
|
@@ -3,10 +3,54 @@
|
|
3
3
|
require "active_support/core_ext/object/try"
|
4
4
|
|
5
5
|
module ActiveStorage
|
6
|
+
# = Active Storage \Attached \Model
|
7
|
+
#
|
6
8
|
# Provides the class-level DSL for declaring an Active Record model's attachments.
|
7
9
|
module Attached::Model
|
8
10
|
extend ActiveSupport::Concern
|
9
11
|
|
12
|
+
##
|
13
|
+
# :method: *_attachment
|
14
|
+
#
|
15
|
+
# Returns the attachment for the +has_one_attached+.
|
16
|
+
#
|
17
|
+
# User.last.avatar_attachment
|
18
|
+
|
19
|
+
##
|
20
|
+
# :method: *_attachments
|
21
|
+
#
|
22
|
+
# Returns the attachments for the +has_many_attached+.
|
23
|
+
#
|
24
|
+
# Gallery.last.photos_attachments
|
25
|
+
|
26
|
+
##
|
27
|
+
# :method: *_blob
|
28
|
+
#
|
29
|
+
# Returns the blob for the +has_one_attached+ attachment.
|
30
|
+
#
|
31
|
+
# User.last.avatar_blob
|
32
|
+
|
33
|
+
##
|
34
|
+
# :method: *_blobs
|
35
|
+
#
|
36
|
+
# Returns the blobs for the +has_many_attached+ attachments.
|
37
|
+
#
|
38
|
+
# Gallery.last.photos_blobs
|
39
|
+
|
40
|
+
##
|
41
|
+
# :method: with_attached_*
|
42
|
+
#
|
43
|
+
# Includes the attached blobs in your query to avoid N+1 queries.
|
44
|
+
#
|
45
|
+
# If +ActiveStorage.track_variants+ is enabled, it will also include the
|
46
|
+
# variants record and their attached blobs.
|
47
|
+
#
|
48
|
+
# User.with_attached_avatar
|
49
|
+
#
|
50
|
+
# Use the plural form for +has_many_attached+:
|
51
|
+
#
|
52
|
+
# Gallery.with_attached_photos
|
53
|
+
|
10
54
|
class_methods do
|
11
55
|
# Specifies the relation between a single attachment and the model.
|
12
56
|
#
|
@@ -59,7 +103,7 @@ module ActiveStorage
|
|
59
103
|
|
60
104
|
def #{name}=(attachable)
|
61
105
|
attachment_changes["#{name}"] =
|
62
|
-
if attachable.nil?
|
106
|
+
if attachable.nil? || attachable == ""
|
63
107
|
ActiveStorage::Attached::Changes::DeleteOne.new("#{name}", self)
|
64
108
|
else
|
65
109
|
ActiveStorage::Attached::Changes::CreateOne.new("#{name}", self, attachable)
|
@@ -70,7 +114,13 @@ module ActiveStorage
|
|
70
114
|
has_one :"#{name}_attachment", -> { where(name: name) }, class_name: "ActiveStorage::Attachment", as: :record, inverse_of: :record, dependent: :destroy, strict_loading: strict_loading
|
71
115
|
has_one :"#{name}_blob", through: :"#{name}_attachment", class_name: "ActiveStorage::Blob", source: :blob, strict_loading: strict_loading
|
72
116
|
|
73
|
-
scope :"with_attached_#{name}", -> {
|
117
|
+
scope :"with_attached_#{name}", -> {
|
118
|
+
if ActiveStorage.track_variants
|
119
|
+
includes("#{name}_attachment": { blob: { variant_records: { image_attachment: :blob } } })
|
120
|
+
else
|
121
|
+
includes("#{name}_attachment": :blob)
|
122
|
+
end
|
123
|
+
}
|
74
124
|
|
75
125
|
after_save { attachment_changes[name.to_s]&.save }
|
76
126
|
|
@@ -83,6 +133,7 @@ module ActiveStorage
|
|
83
133
|
{ dependent: dependent, service_name: service },
|
84
134
|
self
|
85
135
|
)
|
136
|
+
yield reflection if block_given?
|
86
137
|
ActiveRecord::Reflection.add_attachment_reflection(self, name, reflection)
|
87
138
|
end
|
88
139
|
|
@@ -136,36 +187,27 @@ module ActiveStorage
|
|
136
187
|
end
|
137
188
|
|
138
189
|
def #{name}=(attachables)
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
ActiveStorage::Attached::Changes::CreateMany.new("#{name}", self, attachables)
|
145
|
-
end
|
190
|
+
attachables = Array(attachables).compact_blank
|
191
|
+
pending_uploads = attachment_changes["#{name}"].try(:pending_uploads)
|
192
|
+
|
193
|
+
attachment_changes["#{name}"] = if attachables.none?
|
194
|
+
ActiveStorage::Attached::Changes::DeleteMany.new("#{name}", self)
|
146
195
|
else
|
147
|
-
|
148
|
-
attachment_changes["#{name}"] =
|
149
|
-
ActiveStorage::Attached::Changes::CreateMany.new("#{name}", self, #{name}.blobs + attachables)
|
150
|
-
end
|
196
|
+
ActiveStorage::Attached::Changes::CreateMany.new("#{name}", self, attachables, pending_uploads: pending_uploads)
|
151
197
|
end
|
152
198
|
end
|
153
199
|
CODE
|
154
200
|
|
155
|
-
has_many :"#{name}_attachments", -> { where(name: name) }, as: :record, class_name: "ActiveStorage::Attachment", inverse_of: :record, dependent: :destroy, strict_loading: strict_loading
|
156
|
-
def purge
|
157
|
-
each(&:purge)
|
158
|
-
reset
|
159
|
-
end
|
160
|
-
|
161
|
-
def purge_later
|
162
|
-
each(&:purge_later)
|
163
|
-
reset
|
164
|
-
end
|
165
|
-
end
|
201
|
+
has_many :"#{name}_attachments", -> { where(name: name) }, as: :record, class_name: "ActiveStorage::Attachment", inverse_of: :record, dependent: :destroy, strict_loading: strict_loading
|
166
202
|
has_many :"#{name}_blobs", through: :"#{name}_attachments", class_name: "ActiveStorage::Blob", source: :blob, strict_loading: strict_loading
|
167
203
|
|
168
|
-
scope :"with_attached_#{name}", -> {
|
204
|
+
scope :"with_attached_#{name}", -> {
|
205
|
+
if ActiveStorage.track_variants
|
206
|
+
includes("#{name}_attachments": { blob: { variant_records: { image_attachment: :blob } } })
|
207
|
+
else
|
208
|
+
includes("#{name}_attachments": :blob)
|
209
|
+
end
|
210
|
+
}
|
169
211
|
|
170
212
|
after_save { attachment_changes[name.to_s]&.save }
|
171
213
|
|
@@ -178,6 +220,7 @@ module ActiveStorage
|
|
178
220
|
{ dependent: dependent, service_name: service },
|
179
221
|
self
|
180
222
|
)
|
223
|
+
yield reflection if block_given?
|
181
224
|
ActiveRecord::Reflection.add_attachment_reflection(self, name, reflection)
|
182
225
|
end
|
183
226
|
|
@@ -187,25 +230,33 @@ module ActiveStorage
|
|
187
230
|
ActiveStorage::Blob.services.fetch(service) do
|
188
231
|
raise ArgumentError, "Cannot configure service :#{service} for #{name}##{association_name}"
|
189
232
|
end
|
233
|
+
else
|
234
|
+
validate_global_service_configuration
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
def validate_global_service_configuration
|
239
|
+
if connected? && ActiveStorage::Blob.table_exists? && Rails.configuration.active_storage.service.nil?
|
240
|
+
raise RuntimeError, "Missing Active Storage service name. Specify Active Storage service name for config.active_storage.service in config/environments/#{Rails.env}.rb"
|
190
241
|
end
|
191
242
|
end
|
192
243
|
end
|
193
244
|
|
194
|
-
def attachment_changes
|
245
|
+
def attachment_changes # :nodoc:
|
195
246
|
@attachment_changes ||= {}
|
196
247
|
end
|
197
248
|
|
198
|
-
def changed_for_autosave?
|
249
|
+
def changed_for_autosave? # :nodoc:
|
199
250
|
super || attachment_changes.any?
|
200
251
|
end
|
201
252
|
|
202
|
-
def initialize_dup(*)
|
253
|
+
def initialize_dup(*) # :nodoc:
|
203
254
|
super
|
204
255
|
@active_storage_attached = nil
|
205
256
|
@attachment_changes = nil
|
206
257
|
end
|
207
258
|
|
208
|
-
def reload(*)
|
259
|
+
def reload(*) # :nodoc:
|
209
260
|
super.tap { @attachment_changes = nil }
|
210
261
|
end
|
211
262
|
end
|
@@ -1,8 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveStorage
|
4
|
+
# = Active Storage \Attached \One
|
5
|
+
#
|
4
6
|
# Representation of a single attachment to a model.
|
5
7
|
class Attached::One < Attached
|
8
|
+
##
|
9
|
+
# :method: purge
|
10
|
+
#
|
11
|
+
# Directly purges the attachment (i.e. destroys the blob and
|
12
|
+
# attachment and deletes the file on the service).
|
13
|
+
delegate :purge, to: :purge_one
|
14
|
+
|
15
|
+
##
|
16
|
+
# :method: purge_later
|
17
|
+
#
|
18
|
+
# Purges the attachment through the queuing system.
|
19
|
+
delegate :purge_later, to: :purge_one
|
20
|
+
|
21
|
+
##
|
22
|
+
# :method: detach
|
23
|
+
#
|
24
|
+
# Deletes the attachment without purging it, leaving its blob in place.
|
25
|
+
delegate :detach, to: :detach_one
|
26
|
+
|
6
27
|
delegate_missing_to :attachment, allow_nil: true
|
7
28
|
|
8
29
|
# Returns the associated attachment record.
|
@@ -13,6 +34,13 @@ module ActiveStorage
|
|
13
34
|
change.present? ? change.attachment : record.public_send("#{name}_attachment")
|
14
35
|
end
|
15
36
|
|
37
|
+
# Returns +true+ if an attachment is not attached.
|
38
|
+
#
|
39
|
+
# class User < ApplicationRecord
|
40
|
+
# has_one_attached :avatar
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# User.new.avatar.blank? # => true
|
16
44
|
def blank?
|
17
45
|
!attached?
|
18
46
|
end
|
@@ -25,15 +53,14 @@ module ActiveStorage
|
|
25
53
|
#
|
26
54
|
# person.avatar.attach(params[:avatar]) # ActionDispatch::Http::UploadedFile object
|
27
55
|
# 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/
|
56
|
+
# person.avatar.attach(io: File.open("/path/to/face.jpg"), filename: "face.jpg", content_type: "image/jpeg")
|
29
57
|
# person.avatar.attach(avatar_blob) # ActiveStorage::Blob object
|
30
58
|
def attach(attachable)
|
59
|
+
record.public_send("#{name}=", attachable)
|
31
60
|
if record.persisted? && !record.changed?
|
32
|
-
record.
|
33
|
-
record.save
|
34
|
-
else
|
35
|
-
record.public_send("#{name}=", attachable)
|
61
|
+
return if !record.save
|
36
62
|
end
|
63
|
+
record.public_send("#{name}")
|
37
64
|
end
|
38
65
|
|
39
66
|
# Returns +true+ if an attachment has been made.
|
@@ -47,34 +74,13 @@ module ActiveStorage
|
|
47
74
|
attachment.present?
|
48
75
|
end
|
49
76
|
|
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
|
77
|
+
private
|
78
|
+
def purge_one
|
79
|
+
Attached::Changes::PurgeOne.new(name, record, attachment)
|
72
80
|
end
|
73
|
-
end
|
74
81
|
|
75
|
-
|
76
|
-
|
77
|
-
record.public_send("#{name}_attachment=", attachment)
|
82
|
+
def detach_one
|
83
|
+
Attached::Changes::DetachOne.new(name, record, attachment)
|
78
84
|
end
|
79
85
|
end
|
80
86
|
end
|
@@ -3,6 +3,8 @@
|
|
3
3
|
require "active_support/core_ext/module/delegation"
|
4
4
|
|
5
5
|
module ActiveStorage
|
6
|
+
# = Active Storage \Attached
|
7
|
+
#
|
6
8
|
# Abstract base class for the concrete ActiveStorage::Attached::One and ActiveStorage::Attached::Many
|
7
9
|
# classes that both provide proxy access to the blob association for a record.
|
8
10
|
class Attached
|
@@ -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
|