activestorage 6.1.7.7 → 7.0.0.alpha1

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.

Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +126 -321
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +25 -11
  5. data/app/assets/javascripts/activestorage.esm.js +844 -0
  6. data/app/assets/javascripts/activestorage.js +257 -376
  7. data/app/controllers/active_storage/base_controller.rb +1 -10
  8. data/app/controllers/active_storage/blobs/proxy_controller.rb +14 -5
  9. data/app/controllers/active_storage/blobs/redirect_controller.rb +6 -4
  10. data/app/controllers/active_storage/representations/base_controller.rb +5 -1
  11. data/app/controllers/active_storage/representations/proxy_controller.rb +6 -5
  12. data/app/controllers/active_storage/representations/redirect_controller.rb +6 -4
  13. data/app/controllers/concerns/active_storage/set_blob.rb +6 -2
  14. data/app/controllers/concerns/active_storage/set_current.rb +3 -3
  15. data/app/controllers/concerns/active_storage/streaming.rb +65 -0
  16. data/app/javascript/activestorage/ujs.js +1 -1
  17. data/app/models/active_storage/attachment.rb +35 -2
  18. data/app/models/active_storage/blob/representable.rb +7 -5
  19. data/app/models/active_storage/blob.rb +26 -27
  20. data/app/models/active_storage/current.rb +12 -2
  21. data/app/models/active_storage/preview.rb +6 -4
  22. data/app/models/active_storage/record.rb +1 -1
  23. data/app/models/active_storage/variant.rb +6 -9
  24. data/app/models/active_storage/variant_record.rb +2 -0
  25. data/app/models/active_storage/variant_with_record.rb +9 -5
  26. data/app/models/active_storage/variation.rb +3 -3
  27. data/config/routes.rb +10 -10
  28. data/db/migrate/20170806125915_create_active_storage_tables.rb +11 -2
  29. data/db/update_migrate/20190112182829_add_service_name_to_active_storage_blobs.rb +0 -4
  30. data/db/update_migrate/20191206030411_create_active_storage_variant_records.rb +1 -3
  31. data/lib/active_storage/analyzer/audio_analyzer.rb +65 -0
  32. data/lib/active_storage/analyzer/image_analyzer/image_magick.rb +39 -0
  33. data/lib/active_storage/analyzer/image_analyzer/vips.rb +49 -0
  34. data/lib/active_storage/analyzer/image_analyzer.rb +2 -30
  35. data/lib/active_storage/analyzer/video_analyzer.rb +26 -11
  36. data/lib/active_storage/analyzer.rb +8 -4
  37. data/lib/active_storage/attached/changes/create_many.rb +7 -3
  38. data/lib/active_storage/attached/changes/create_one.rb +1 -1
  39. data/lib/active_storage/attached/changes/create_one_of_many.rb +1 -1
  40. data/lib/active_storage/attached/changes/delete_many.rb +1 -1
  41. data/lib/active_storage/attached/changes/delete_one.rb +1 -1
  42. data/lib/active_storage/attached/changes/detach_many.rb +18 -0
  43. data/lib/active_storage/attached/changes/detach_one.rb +24 -0
  44. data/lib/active_storage/attached/changes/purge_many.rb +27 -0
  45. data/lib/active_storage/attached/changes/purge_one.rb +27 -0
  46. data/lib/active_storage/attached/changes.rb +7 -1
  47. data/lib/active_storage/attached/many.rb +27 -15
  48. data/lib/active_storage/attached/model.rb +31 -5
  49. data/lib/active_storage/attached/one.rb +32 -27
  50. data/lib/active_storage/downloader.rb +2 -2
  51. data/lib/active_storage/engine.rb +28 -16
  52. data/lib/active_storage/fixture_set.rb +76 -0
  53. data/lib/active_storage/gem_version.rb +4 -4
  54. data/lib/active_storage/previewer/video_previewer.rb +0 -2
  55. data/lib/active_storage/previewer.rb +4 -4
  56. data/lib/active_storage/reflection.rb +12 -2
  57. data/lib/active_storage/service/azure_storage_service.rb +1 -1
  58. data/lib/active_storage/service/configurator.rb +1 -1
  59. data/lib/active_storage/service/disk_service.rb +13 -18
  60. data/lib/active_storage/service/gcs_service.rb +91 -7
  61. data/lib/active_storage/service/mirror_service.rb +1 -1
  62. data/lib/active_storage/service/registry.rb +1 -1
  63. data/lib/active_storage/service/s3_service.rb +4 -4
  64. data/lib/active_storage/service.rb +3 -3
  65. data/lib/active_storage/transformers/image_processing_transformer.rb +1 -66
  66. data/lib/active_storage/transformers/transformer.rb +1 -1
  67. data/lib/active_storage.rb +3 -292
  68. metadata +32 -25
  69. data/app/controllers/concerns/active_storage/disable_session.rb +0 -12
  70. data/app/controllers/concerns/active_storage/set_headers.rb +0 -12
@@ -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/jpg")
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
- # Deletes associated attachments without purging them, leaving their respective blobs in place.
51
- def detach
52
- attachments.delete_all if attached?
53
- end
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
- # :method: purge_later
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
 
@@ -144,6 +145,12 @@ module ActiveStorage
144
145
  ActiveStorage::Attached::Changes::CreateMany.new("#{name}", self, attachables)
145
146
  end
146
147
  else
148
+ ActiveSupport::Deprecation.warn \
149
+ "config.active_storage.replace_on_assign_to_many is deprecated and will be removed in Rails 7.1. " \
150
+ "Make sure that your code works well with config.active_storage.replace_on_assign_to_many set to true before upgrading. " \
151
+ "To append new attachables to the Active Storage association, prefer using `attach`. " \
152
+ "Using association setter would result in purging the existing attached attachments and replacing them with new ones."
153
+
147
154
  if Array(attachables).any?
148
155
  attachment_changes["#{name}"] =
149
156
  ActiveStorage::Attached::Changes::CreateMany.new("#{name}", self, #{name}.blobs + attachables)
@@ -154,18 +161,36 @@ module ActiveStorage
154
161
 
155
162
  has_many :"#{name}_attachments", -> { where(name: name) }, as: :record, class_name: "ActiveStorage::Attachment", inverse_of: :record, dependent: :destroy, strict_loading: strict_loading do
156
163
  def purge
164
+ deprecate(:purge)
157
165
  each(&:purge)
158
166
  reset
159
167
  end
160
168
 
161
169
  def purge_later
170
+ deprecate(:purge_later)
162
171
  each(&:purge_later)
163
172
  reset
164
173
  end
174
+
175
+ private
176
+ def deprecate(action)
177
+ reflection_name = proxy_association.reflection.name
178
+ attached_name = reflection_name.to_s.partition("_").first
179
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
180
+ Calling `#{action}` from `#{reflection_name}` is deprecated and will be removed in Rails 7.1.
181
+ To migrate to Rails 7.1's behavior call `#{action}` from `#{attached_name}` instead: `#{attached_name}.#{action}`.
182
+ MSG
183
+ end
165
184
  end
166
185
  has_many :"#{name}_blobs", through: :"#{name}_attachments", class_name: "ActiveStorage::Blob", source: :blob, strict_loading: strict_loading
167
186
 
168
- scope :"with_attached_#{name}", -> { includes("#{name}_attachments": :blob) }
187
+ scope :"with_attached_#{name}", -> {
188
+ if ActiveStorage.track_variants
189
+ includes("#{name}_attachments": { blob: :variant_records })
190
+ else
191
+ includes("#{name}_attachments": :blob)
192
+ end
193
+ }
169
194
 
170
195
  after_save { attachment_changes[name.to_s]&.save }
171
196
 
@@ -178,6 +203,7 @@ module ActiveStorage
178
203
  { dependent: dependent, service_name: service },
179
204
  self
180
205
  )
206
+ yield reflection if block_given?
181
207
  ActiveRecord::Reflection.add_attachment_reflection(self, name, reflection)
182
208
  end
183
209
 
@@ -191,21 +217,21 @@ module ActiveStorage
191
217
  end
192
218
  end
193
219
 
194
- def attachment_changes #:nodoc:
220
+ def attachment_changes # :nodoc:
195
221
  @attachment_changes ||= {}
196
222
  end
197
223
 
198
- def changed_for_autosave? #:nodoc:
224
+ def changed_for_autosave? # :nodoc:
199
225
  super || attachment_changes.any?
200
226
  end
201
227
 
202
- def initialize_dup(*) #:nodoc:
228
+ def initialize_dup(*) # :nodoc:
203
229
  super
204
230
  @active_storage_attached = nil
205
231
  @attachment_changes = nil
206
232
  end
207
233
 
208
- def reload(*) #:nodoc:
234
+ def reload(*) # :nodoc:
209
235
  super.tap { @attachment_changes = nil }
210
236
  end
211
237
  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/jpg")
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
- # Deletes the attachment without purging it, leaving its blob in place.
51
- def detach
52
- if attached?
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
- private
76
- def write_attachment(attachment)
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,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveStorage
4
- class Downloader #:nodoc:
4
+ class Downloader # :nodoc:
5
5
  attr_reader :service
6
6
 
7
7
  def initialize(service)
@@ -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,7 +27,7 @@ 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
30
33
 
@@ -39,6 +42,9 @@ module ActiveStorage
39
42
  image/vnd.adobe.photoshop
40
43
  image/vnd.microsoft.icon
41
44
  image/webp
45
+ image/avif
46
+ image/heic
47
+ image/heif
42
48
  )
43
49
 
44
50
  config.active_storage.web_image_content_types = %w(
@@ -86,25 +92,11 @@ module ActiveStorage
86
92
  ActiveStorage.draw_routes = app.config.active_storage.draw_routes != false
87
93
  ActiveStorage.resolve_model_to_route = app.config.active_storage.resolve_model_to_route || :rails_storage_redirect
88
94
 
89
- ActiveStorage.supported_image_processing_methods += app.config.active_storage.supported_image_processing_methods || []
90
- ActiveStorage.unsupported_image_processing_arguments = app.config.active_storage.unsupported_image_processing_arguments || %w(
91
- -debug
92
- -display
93
- -distribute-cache
94
- -help
95
- -path
96
- -print
97
- -set
98
- -verbose
99
- -version
100
- -write
101
- -write-mask
102
- )
103
-
104
95
  ActiveStorage.variable_content_types = app.config.active_storage.variable_content_types || []
105
96
  ActiveStorage.web_image_content_types = app.config.active_storage.web_image_content_types || []
106
97
  ActiveStorage.content_types_to_serve_as_binary = app.config.active_storage.content_types_to_serve_as_binary || []
107
98
  ActiveStorage.service_urls_expire_in = app.config.active_storage.service_urls_expire_in || 5.minutes
99
+ ActiveStorage.urls_expire_in = app.config.active_storage.urls_expire_in
108
100
  ActiveStorage.content_types_allowed_inline = app.config.active_storage.content_types_allowed_inline || []
109
101
  ActiveStorage.binary_content_type = app.config.active_storage.binary_content_type || "application/octet-stream"
110
102
  ActiveStorage.video_preview_arguments = app.config.active_storage.video_preview_arguments || "-y -vframes 1 -f image2"
@@ -159,5 +151,25 @@ module ActiveStorage
159
151
  ActiveRecord::Reflection.singleton_class.prepend(Reflection::ReflectionExtension)
160
152
  end
161
153
  end
154
+
155
+ initializer "active_storage.asset" do
156
+ if Rails.application.config.respond_to?(:assets)
157
+ Rails.application.config.assets.precompile += %w( activestorage activestorage.esm )
158
+ end
159
+ end
160
+
161
+ initializer "active_storage.fixture_set" do
162
+ ActiveSupport.on_load(:active_record_fixture_set) do
163
+ ActiveStorage::FixtureSet.file_fixture_path ||= Rails.root.join(*[
164
+ ENV.fetch("FIXTURES_PATH") { File.join("test", "fixtures") },
165
+ ENV["FIXTURES_DIR"],
166
+ "files"
167
+ ].compact_blank)
168
+ end
169
+
170
+ ActiveSupport.on_load(:active_support_test_case) do
171
+ ActiveStorage::FixtureSet.file_fixture_path = ActiveSupport::TestCase.file_fixture_path
172
+ end
173
+ end
162
174
  end
163
175
  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
@@ -7,10 +7,10 @@ module ActiveStorage
7
7
  end
8
8
 
9
9
  module VERSION
10
- MAJOR = 6
11
- MINOR = 1
12
- TINY = 7
13
- PRE = "7"
10
+ MAJOR = 7
11
+ MINOR = 0
12
+ TINY = 0
13
+ PRE = "alpha1"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "shellwords"
4
-
5
3
  module ActiveStorage
6
4
  class Previewer::VideoPreviewer < Previewer
7
5
  class << self
@@ -26,7 +26,7 @@ module ActiveStorage
26
26
 
27
27
  private
28
28
  # Downloads the blob to a tempfile on disk. Yields the tempfile.
29
- def download_blob_to_tempfile(&block) #:doc:
29
+ def download_blob_to_tempfile(&block) # :doc:
30
30
  blob.open tmpdir: tmpdir, &block
31
31
  end
32
32
 
@@ -44,7 +44,7 @@ module ActiveStorage
44
44
  # end
45
45
  #
46
46
  # The output tempfile is opened in the directory returned by #tmpdir.
47
- def draw(*argv) #:doc:
47
+ def draw(*argv) # :doc:
48
48
  open_tempfile do |file|
49
49
  instrument :preview, key: blob.key do
50
50
  capture(*argv, to: file)
@@ -83,11 +83,11 @@ module ActiveStorage
83
83
  to.rewind
84
84
  end
85
85
 
86
- def logger #:doc:
86
+ def logger # :doc:
87
87
  ActiveStorage.logger
88
88
  end
89
89
 
90
- def tmpdir #:doc:
90
+ def tmpdir # :doc:
91
91
  Dir.tmpdir
92
92
  end
93
93
  end
@@ -2,9 +2,19 @@
2
2
 
3
3
  module ActiveStorage
4
4
  module Reflection
5
+ class HasAttachedReflection < ActiveRecord::Reflection::MacroReflection # :nodoc:
6
+ def variant(name, transformations)
7
+ variants[name] = transformations
8
+ end
9
+
10
+ def variants
11
+ @variants ||= {}
12
+ end
13
+ end
14
+
5
15
  # Holds all the metadata about a has_one_attached attachment as it was
6
16
  # specified in the Active Record class.
7
- class HasOneAttachedReflection < ActiveRecord::Reflection::MacroReflection #:nodoc:
17
+ class HasOneAttachedReflection < HasAttachedReflection # :nodoc:
8
18
  def macro
9
19
  :has_one_attached
10
20
  end
@@ -12,7 +22,7 @@ module ActiveStorage
12
22
 
13
23
  # Holds all the metadata about a has_many_attached attachment as it was
14
24
  # specified in the Active Record class.
15
- class HasManyAttachedReflection < ActiveRecord::Reflection::MacroReflection #:nodoc:
25
+ class HasManyAttachedReflection < HasAttachedReflection # :nodoc:
16
26
  def macro
17
27
  :has_many_attached
18
28
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- gem "azure-storage-blob", ">= 1.1"
3
+ gem "azure-storage-blob", ">= 2.0"
4
4
 
5
5
  require "active_support/core_ext/numeric/bytes"
6
6
  require "azure/storage/blob"
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveStorage
4
- class Service::Configurator #:nodoc:
4
+ class Service::Configurator # :nodoc:
5
5
  attr_reader :configurations
6
6
 
7
7
  def self.build(service_name, configurations)
@@ -2,14 +2,14 @@
2
2
 
3
3
  require "fileutils"
4
4
  require "pathname"
5
- require "digest/md5"
5
+ require "openssl"
6
6
  require "active_support/core_ext/numeric/bytes"
7
7
 
8
8
  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_accessor :root
13
13
 
14
14
  def initialize(root:, public: false, **options)
15
15
  @root = root
@@ -86,11 +86,9 @@ module ActiveStorage
86
86
  purpose: :blob_token
87
87
  )
88
88
 
89
- generated_url = url_helpers.update_rails_disk_service_url(verified_token_with_expiration, host: current_host)
90
-
91
- payload[:url] = generated_url
92
-
93
- generated_url
89
+ url_helpers.update_rails_disk_service_url(verified_token_with_expiration, url_options).tap do |generated_url|
90
+ payload[:url] = generated_url
91
+ end
94
92
  end
95
93
  end
96
94
 
@@ -98,7 +96,7 @@ module ActiveStorage
98
96
  { "Content-Type" => content_type }
99
97
  end
100
98
 
101
- def path_for(key) #:nodoc:
99
+ def path_for(key) # :nodoc:
102
100
  File.join root, folder_for(key), key
103
101
  end
104
102
 
@@ -124,14 +122,11 @@ module ActiveStorage
124
122
  purpose: :blob_key
125
123
  )
126
124
 
127
- current_uri = URI.parse(current_host)
125
+ if url_options.blank?
126
+ raise ArgumentError, "Cannot generate URL for #{filename} using Disk service, please set ActiveStorage::Current.url_options."
127
+ end
128
128
 
129
- url_helpers.rails_disk_service_url(verified_key_with_expiration,
130
- protocol: current_uri.scheme,
131
- host: current_uri.host,
132
- port: current_uri.port,
133
- filename: filename
134
- )
129
+ url_helpers.rails_disk_service_url(verified_key_with_expiration, filename: filename, **url_options)
135
130
  end
136
131
 
137
132
 
@@ -154,7 +149,7 @@ module ActiveStorage
154
149
  end
155
150
 
156
151
  def ensure_integrity_of(key, checksum)
157
- unless Digest::MD5.file(path_for(key)).base64digest == checksum
152
+ unless OpenSSL::Digest::MD5.file(path_for(key)).base64digest == checksum
158
153
  delete key
159
154
  raise ActiveStorage::IntegrityError
160
155
  end
@@ -164,8 +159,8 @@ module ActiveStorage
164
159
  @url_helpers ||= Rails.application.routes.url_helpers
165
160
  end
166
161
 
167
- def current_host
168
- ActiveStorage::Current.host
162
+ def url_options
163
+ ActiveStorage::Current.url_options
169
164
  end
170
165
  end
171
166
  end