activestorage 7.1.0 → 7.2.2.1

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.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +51 -200
  3. data/app/assets/javascripts/activestorage.esm.js +3 -3
  4. data/app/assets/javascripts/activestorage.js +3 -3
  5. data/app/controllers/active_storage/representations/proxy_controller.rb +1 -1
  6. data/app/javascript/activestorage/ujs.js +3 -3
  7. data/app/jobs/active_storage/preview_image_job.rb +16 -0
  8. data/app/jobs/active_storage/transform_job.rb +2 -2
  9. data/app/models/active_storage/attachment.rb +19 -8
  10. data/app/models/active_storage/blob/representable.rb +9 -1
  11. data/app/models/active_storage/blob/servable.rb +22 -0
  12. data/app/models/active_storage/blob.rb +40 -33
  13. data/app/models/active_storage/filename.rb +0 -4
  14. data/app/models/active_storage/preview.rb +18 -5
  15. data/app/models/active_storage/variant.rb +2 -0
  16. data/app/models/active_storage/variant_record.rb +0 -2
  17. data/app/models/active_storage/variant_with_record.rb +2 -0
  18. data/db/migrate/20170806125915_create_active_storage_tables.rb +1 -1
  19. data/lib/active_storage/analyzer/image_analyzer/vips.rb +5 -9
  20. data/lib/active_storage/analyzer/video_analyzer.rb +6 -2
  21. data/lib/active_storage/attached/changes/create_one.rb +6 -1
  22. data/lib/active_storage/attached/changes/create_one_of_many.rb +5 -1
  23. data/lib/active_storage/attached/model.rb +40 -27
  24. data/lib/active_storage/engine.rb +3 -9
  25. data/lib/active_storage/fixture_set.rb +5 -1
  26. data/lib/active_storage/gem_version.rb +3 -3
  27. data/lib/active_storage/previewer/mupdf_previewer.rb +6 -2
  28. data/lib/active_storage/previewer/poppler_pdf_previewer.rb +6 -2
  29. data/lib/active_storage/previewer/video_previewer.rb +1 -1
  30. data/lib/active_storage/transformers/image_processing_transformer.rb +1 -1
  31. data/lib/active_storage.rb +2 -17
  32. metadata +20 -18
@@ -31,15 +31,19 @@
31
31
  # These libraries are not provided by \Rails. You must install them yourself to use the built-in previewers. Before you
32
32
  # install and use third-party software, make sure you understand the licensing implications of doing so.
33
33
  class ActiveStorage::Preview
34
+ include ActiveStorage::Blob::Servable
35
+
34
36
  class UnprocessedError < StandardError; end
35
37
 
38
+ delegate :filename, :content_type, to: :presentation
39
+
36
40
  attr_reader :blob, :variation
37
41
 
38
42
  def initialize(blob, variation_or_variation_key)
39
43
  @blob, @variation = blob, ActiveStorage::Variation.wrap(variation_or_variation_key)
40
44
  end
41
45
 
42
- # Processes the preview if it has not been processed yet. Returns the receiving Preview instance for convenience:
46
+ # Processes the preview if it has not been processed yet. Returns the receiving +ActiveStorage::Preview+ instance for convenience:
43
47
  #
44
48
  # blob.preview(resize_to_limit: [100, 100]).processed.url
45
49
  #
@@ -47,6 +51,7 @@ class ActiveStorage::Preview
47
51
  # image is stored with the blob, it is only generated once.
48
52
  def processed
49
53
  process unless processed?
54
+ variant.processed if variant?
50
55
  self
51
56
  end
52
57
 
@@ -62,7 +67,7 @@ class ActiveStorage::Preview
62
67
  # a stable URL that redirects to the URL returned by this method.
63
68
  def url(**options)
64
69
  if processed?
65
- variant.url(**options)
70
+ presentation.url(**options)
66
71
  else
67
72
  raise UnprocessedError
68
73
  end
@@ -71,7 +76,7 @@ class ActiveStorage::Preview
71
76
  # Returns a combination key of the blob and the variation that together identifies a specific variant.
72
77
  def key
73
78
  if processed?
74
- variant.key
79
+ presentation.key
75
80
  else
76
81
  raise UnprocessedError
77
82
  end
@@ -84,7 +89,7 @@ class ActiveStorage::Preview
84
89
  # if the preview has not been processed yet.
85
90
  def download(&block)
86
91
  if processed?
87
- variant.download(&block)
92
+ presentation.download(&block)
88
93
  else
89
94
  raise UnprocessedError
90
95
  end
@@ -104,7 +109,15 @@ class ActiveStorage::Preview
104
109
  end
105
110
 
106
111
  def variant
107
- image.variant(variation).processed
112
+ image.variant(variation)
113
+ end
114
+
115
+ def variant?
116
+ variation.transformations.present?
117
+ end
118
+
119
+ def presentation
120
+ variant? ? variant.processed : image
108
121
  end
109
122
 
110
123
 
@@ -53,6 +53,8 @@
53
53
  # * {ImageProcessing::Vips}[https://github.com/janko/image_processing/blob/master/doc/vips.md#methods]
54
54
  # * {ruby-vips reference}[http://www.rubydoc.info/gems/ruby-vips/Vips/Image]
55
55
  class ActiveStorage::Variant
56
+ include ActiveStorage::Blob::Servable
57
+
56
58
  attr_reader :blob, :variation
57
59
  delegate :service, to: :blob
58
60
  delegate :content_type, to: :variation
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ActiveStorage::VariantRecord < ActiveStorage::Record
4
- self.table_name = "active_storage_variant_records"
5
-
6
4
  belongs_to :blob
7
5
  has_one_attached :image
8
6
  end
@@ -5,6 +5,8 @@
5
5
  # Like an ActiveStorage::Variant, but keeps detail about the variant in the database as an
6
6
  # ActiveStorage::VariantRecord. This is only used if +ActiveStorage.track_variants+ is enabled.
7
7
  class ActiveStorage::VariantWithRecord
8
+ include ActiveStorage::Blob::Servable
9
+
8
10
  attr_reader :blob, :variation
9
11
  delegate :service, to: :blob
10
12
  delegate :content_type, to: :variation
@@ -51,6 +51,6 @@ class CreateActiveStorageTables < ActiveRecord::Migration[7.0]
51
51
  setting = config.options[config.orm][:primary_key_type]
52
52
  primary_key_type = setting || :primary_key
53
53
  foreign_key_type = setting || :bigint
54
- [primary_key_type, foreign_key_type]
54
+ [ primary_key_type, foreign_key_type ]
55
55
  end
56
56
  end
@@ -19,13 +19,16 @@ module ActiveStorage
19
19
 
20
20
  download_blob_to_tempfile do |file|
21
21
  image = instrument("vips") do
22
+ # ruby-vips will raise Vips::Error if it can't find an appropriate loader for the file
22
23
  ::Vips::Image.new_from_file(file.path, access: :sequential)
24
+ rescue ::Vips::Error
25
+ logger.info "Skipping image analysis because Vips doesn't support the file"
26
+ nil
23
27
  end
24
28
 
25
- if valid_image?(image)
29
+ if image
26
30
  yield image
27
31
  else
28
- logger.info "Skipping image analysis because Vips doesn't support the file"
29
32
  {}
30
33
  end
31
34
  rescue ::Vips::Error => error
@@ -40,12 +43,5 @@ module ActiveStorage
40
43
  rescue ::Vips::Error
41
44
  false
42
45
  end
43
-
44
- def valid_image?(image)
45
- image.avg
46
- true
47
- rescue ::Vips::Error
48
- false
49
- end
50
46
  end
51
47
  end
@@ -55,11 +55,15 @@ module ActiveStorage
55
55
  def angle
56
56
  if tags["rotate"]
57
57
  Integer(tags["rotate"])
58
- elsif side_data && side_data[0] && side_data[0]["rotation"]
59
- Integer(side_data[0]["rotation"])
58
+ elsif display_matrix && display_matrix["rotation"]
59
+ Integer(display_matrix["rotation"])
60
60
  end
61
61
  end
62
62
 
63
+ def display_matrix
64
+ side_data.detect { |data| data["side_data_type"] == "Display Matrix" }
65
+ end
66
+
63
67
  def display_aspect_ratio
64
68
  if descriptor = video_stream["display_aspect_ratio"]
65
69
  if terms = descriptor.split(":", 2)
@@ -118,7 +118,12 @@ module ActiveStorage
118
118
  end
119
119
 
120
120
  def attachment_service_name
121
- record.attachment_reflections[name].options[:service_name]
121
+ service_name = record.attachment_reflections[name].options[:service_name]
122
+ if service_name.is_a?(Proc)
123
+ service_name = service_name.call(record)
124
+ ActiveStorage::Blob.validate_service_configuration(service_name, record.class, name)
125
+ end
126
+ service_name
122
127
  end
123
128
  end
124
129
  end
@@ -4,7 +4,11 @@ module ActiveStorage
4
4
  class Attached::Changes::CreateOneOfMany < Attached::Changes::CreateOne # :nodoc:
5
5
  private
6
6
  def find_attachment
7
- record.public_send("#{name}_attachments").detect { |attachment| attachment.blob_id == blob.id }
7
+ if blob.persisted?
8
+ record.public_send("#{name}_attachments").detect { |attachment| attachment.blob_id == blob.id }
9
+ else
10
+ blob.attachments.find { |attachment| attachment.record == record }
11
+ end
8
12
  end
9
13
  end
10
14
  end
@@ -74,16 +74,24 @@ module ActiveStorage
74
74
  # The system has been designed to having you go through the ActiveStorage::Attached::One
75
75
  # proxy that provides the dynamic proxy to the associations and factory methods, like +attach+.
76
76
  #
77
- # If the +:dependent+ option isn't set, the attachment will be purged
78
- # (i.e. destroyed) whenever the record is destroyed.
77
+ # The +:dependent+ option defaults to +:purge_later+. This means the attachment will be
78
+ # purged (i.e. destroyed) in the background whenever the record is destroyed.
79
+ # If an ActiveJob::Backend queue adapter is not set in the application set it to
80
+ # +purge+ instead.
79
81
  #
80
82
  # If you need the attachment to use a service which differs from the globally configured one,
81
- # pass the +:service+ option. For instance:
83
+ # pass the +:service+ option. For example:
82
84
  #
83
85
  # class User < ActiveRecord::Base
84
86
  # has_one_attached :avatar, service: :s3
85
87
  # end
86
88
  #
89
+ # +:service+ can also be specified as a proc, and it will be called with the model instance:
90
+ #
91
+ # class User < ActiveRecord::Base
92
+ # has_one_attached :avatar, service: ->(user) { user.in_europe_region? ? :s3_europe : :s3_usa }
93
+ # end
94
+ #
87
95
  # If you need to enable +strict_loading+ to prevent lazy loading of attachment,
88
96
  # pass the +:strict_loading+ option. You can do:
89
97
  #
@@ -91,8 +99,12 @@ module ActiveStorage
91
99
  # has_one_attached :avatar, strict_loading: true
92
100
  # end
93
101
  #
102
+ # Note: Active Storage relies on polymorphic associations, which in turn store class names in the database.
103
+ # When renaming classes that use <tt>has_one_attached</tt>, make sure to also update the class names in the
104
+ # <tt>active_storage_attachments.record_type</tt> polymorphic type column of
105
+ # the corresponding rows.
94
106
  def has_one_attached(name, dependent: :purge_later, service: nil, strict_loading: false)
95
- validate_service_configuration(name, service)
107
+ ActiveStorage::Blob.validate_service_configuration(service, self, name) unless service.is_a?(Proc)
96
108
 
97
109
  generated_association_methods.class_eval <<-CODE, __FILE__, __LINE__ + 1
98
110
  # frozen_string_literal: true
@@ -116,7 +128,10 @@ module ActiveStorage
116
128
 
117
129
  scope :"with_attached_#{name}", -> {
118
130
  if ActiveStorage.track_variants
119
- includes("#{name}_attachment": { blob: { variant_records: { image_attachment: :blob } } })
131
+ includes("#{name}_attachment": { blob: {
132
+ variant_records: { image_attachment: :blob },
133
+ preview_image_attachment: { blob: { variant_records: { image_attachment: :blob } } }
134
+ } })
120
135
  else
121
136
  includes("#{name}_attachment": :blob)
122
137
  end
@@ -159,16 +174,24 @@ module ActiveStorage
159
174
  # The system has been designed to having you go through the ActiveStorage::Attached::Many
160
175
  # proxy that provides the dynamic proxy to the associations and factory methods, like +#attach+.
161
176
  #
162
- # If the +:dependent+ option isn't set, all the attachments will be purged
163
- # (i.e. destroyed) whenever the record is destroyed.
177
+ # The +:dependent+ option defaults to +:purge_later+. This means the attachments will be
178
+ # purged (i.e. destroyed) in the background whenever the record is destroyed.
179
+ # If an ActiveJob::Backend queue adapter is not set in the application set it to
180
+ # +purge+ instead.
164
181
  #
165
182
  # If you need the attachment to use a service which differs from the globally configured one,
166
- # pass the +:service+ option. For instance:
183
+ # pass the +:service+ option. For example:
167
184
  #
168
185
  # class Gallery < ActiveRecord::Base
169
186
  # has_many_attached :photos, service: :s3
170
187
  # end
171
188
  #
189
+ # +:service+ can also be specified as a proc, and it will be called with the model instance:
190
+ #
191
+ # class Gallery < ActiveRecord::Base
192
+ # has_many_attached :photos, service: ->(gallery) { gallery.personal? ? :personal_s3 : :s3 }
193
+ # end
194
+ #
172
195
  # If you need to enable +strict_loading+ to prevent lazy loading of attachments,
173
196
  # pass the +:strict_loading+ option. You can do:
174
197
  #
@@ -176,8 +199,12 @@ module ActiveStorage
176
199
  # has_many_attached :photos, strict_loading: true
177
200
  # end
178
201
  #
202
+ # Note: Active Storage relies on polymorphic associations, which in turn store class names in the database.
203
+ # When renaming classes that use <tt>has_many</tt>, make sure to also update the class names in the
204
+ # <tt>active_storage_attachments.record_type</tt> polymorphic type column of
205
+ # the corresponding rows.
179
206
  def has_many_attached(name, dependent: :purge_later, service: nil, strict_loading: false)
180
- validate_service_configuration(name, service)
207
+ ActiveStorage::Blob.validate_service_configuration(service, self, name) unless service.is_a?(Proc)
181
208
 
182
209
  generated_association_methods.class_eval <<-CODE, __FILE__, __LINE__ + 1
183
210
  # frozen_string_literal: true
@@ -203,7 +230,10 @@ module ActiveStorage
203
230
 
204
231
  scope :"with_attached_#{name}", -> {
205
232
  if ActiveStorage.track_variants
206
- includes("#{name}_attachments": { blob: { variant_records: { image_attachment: :blob } } })
233
+ includes("#{name}_attachments": { blob: {
234
+ variant_records: { image_attachment: :blob },
235
+ preview_image_attachment: { blob: { variant_records: { image_attachment: :blob } } }
236
+ } })
207
237
  else
208
238
  includes("#{name}_attachments": :blob)
209
239
  end
@@ -223,23 +253,6 @@ module ActiveStorage
223
253
  yield reflection if block_given?
224
254
  ActiveRecord::Reflection.add_attachment_reflection(self, name, reflection)
225
255
  end
226
-
227
- private
228
- def validate_service_configuration(association_name, service)
229
- if service.present?
230
- ActiveStorage::Blob.services.fetch(service) do
231
- raise ArgumentError, "Cannot configure service :#{service} for #{name}##{association_name}"
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"
241
- end
242
- end
243
256
  end
244
257
 
245
258
  def attachment_changes # :nodoc:
@@ -65,6 +65,8 @@ module ActiveStorage
65
65
  )
66
66
 
67
67
  config.active_storage.content_types_allowed_inline = %w(
68
+ image/webp
69
+ image/avif
68
70
  image/png
69
71
  image/gif
70
72
  image/jpeg
@@ -110,20 +112,12 @@ module ActiveStorage
110
112
  ActiveStorage.variable_content_types = app.config.active_storage.variable_content_types || []
111
113
  ActiveStorage.web_image_content_types = app.config.active_storage.web_image_content_types || []
112
114
  ActiveStorage.content_types_to_serve_as_binary = app.config.active_storage.content_types_to_serve_as_binary || []
115
+ ActiveStorage.touch_attachment_records = app.config.active_storage.touch_attachment_records != false
113
116
  ActiveStorage.service_urls_expire_in = app.config.active_storage.service_urls_expire_in || 5.minutes
114
117
  ActiveStorage.urls_expire_in = app.config.active_storage.urls_expire_in
115
118
  ActiveStorage.content_types_allowed_inline = app.config.active_storage.content_types_allowed_inline || []
116
119
  ActiveStorage.binary_content_type = app.config.active_storage.binary_content_type || "application/octet-stream"
117
120
  ActiveStorage.video_preview_arguments = app.config.active_storage.video_preview_arguments || "-y -vframes 1 -f image2"
118
-
119
- unless app.config.active_storage.silence_invalid_content_types_warning.nil?
120
- ActiveStorage.silence_invalid_content_types_warning = app.config.active_storage.silence_invalid_content_types_warning
121
- end
122
-
123
- unless app.config.active_storage.replace_on_assign_to_many.nil?
124
- ActiveStorage.replace_on_assign_to_many = app.config.active_storage.replace_on_assign_to_many
125
- end
126
-
127
121
  ActiveStorage.track_variants = app.config.active_storage.track_variants || false
128
122
  end
129
123
  end
@@ -26,9 +26,13 @@ module ActiveStorage
26
26
  # has_one_attached :thumbnail
27
27
  # end
28
28
  #
29
+ # <code></code>
30
+ #
29
31
  # # fixtures/active_storage/blobs.yml
30
32
  # first_thumbnail_blob: <%= ActiveStorage::FixtureSet.blob filename: "first.png" %>
31
33
  #
34
+ # <code></code>
35
+ #
32
36
  # # fixtures/active_storage/attachments.yml
33
37
  # first_thumbnail_attachment:
34
38
  # name: thumbnail
@@ -48,7 +52,7 @@ module ActiveStorage
48
52
  #
49
53
  # === Examples
50
54
  #
51
- # # tests/fixtures/action_text/blobs.yml
55
+ # # tests/fixtures/active_storage/blobs.yml
52
56
  # second_thumbnail_blob: <%= ActiveStorage::FixtureSet.blob(
53
57
  # filename: "second.svg",
54
58
  # ) %>
@@ -8,9 +8,9 @@ module ActiveStorage
8
8
 
9
9
  module VERSION
10
10
  MAJOR = 7
11
- MINOR = 1
12
- TINY = 0
13
- PRE = nil
11
+ MINOR = 2
12
+ TINY = 2
13
+ PRE = "1"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -4,7 +4,11 @@ module ActiveStorage
4
4
  class Previewer::MuPDFPreviewer < Previewer
5
5
  class << self
6
6
  def accept?(blob)
7
- blob.content_type == "application/pdf" && mutool_exists?
7
+ pdf?(blob.content_type) && mutool_exists?
8
+ end
9
+
10
+ def pdf?(content_type)
11
+ Marcel::Magic.child? content_type, "application/pdf"
8
12
  end
9
13
 
10
14
  def mutool_path
@@ -12,7 +16,7 @@ module ActiveStorage
12
16
  end
13
17
 
14
18
  def mutool_exists?
15
- return @mutool_exists if defined?(@mutool_exists) && !@mutool_exists.nil?
19
+ return @mutool_exists unless @mutool_exists.nil?
16
20
 
17
21
  system mutool_path, out: File::NULL, err: File::NULL
18
22
 
@@ -4,7 +4,11 @@ module ActiveStorage
4
4
  class Previewer::PopplerPDFPreviewer < Previewer
5
5
  class << self
6
6
  def accept?(blob)
7
- blob.content_type == "application/pdf" && pdftoppm_exists?
7
+ pdf?(blob.content_type) && pdftoppm_exists?
8
+ end
9
+
10
+ def pdf?(content_type)
11
+ Marcel::Magic.child? content_type, "application/pdf"
8
12
  end
9
13
 
10
14
  def pdftoppm_path
@@ -12,7 +16,7 @@ module ActiveStorage
12
16
  end
13
17
 
14
18
  def pdftoppm_exists?
15
- return @pdftoppm_exists if defined?(@pdftoppm_exists)
19
+ return @pdftoppm_exists unless @pdftoppm_exists.nil?
16
20
 
17
21
  @pdftoppm_exists = system(pdftoppm_path, "-v", out: File::NULL, err: File::NULL)
18
22
  end
@@ -10,7 +10,7 @@ module ActiveStorage
10
10
  end
11
11
 
12
12
  def ffmpeg_exists?
13
- return @ffmpeg_exists if defined?(@ffmpeg_exists)
13
+ return @ffmpeg_exists unless @ffmpeg_exists.nil?
14
14
 
15
15
  @ffmpeg_exists = system(ffmpeg_path, "-version", out: File::NULL, err: File::NULL)
16
16
  end
@@ -5,7 +5,7 @@ begin
5
5
  rescue LoadError
6
6
  raise LoadError, <<~ERROR.squish
7
7
  Generating image variants require the image_processing gem.
8
- Please add `gem 'image_processing', '~> 1.2'` to your Gemfile.
8
+ Please add `gem "image_processing", "~> 1.2"` to your Gemfile.
9
9
  ERROR
10
10
  end
11
11
 
@@ -35,7 +35,7 @@ require "active_storage/errors"
35
35
  require "marcel"
36
36
 
37
37
  # :markup: markdown
38
- # :include: activestorage/README.md
38
+ # :include: ../README.md
39
39
  module ActiveStorage
40
40
  extend ActiveSupport::Autoload
41
41
 
@@ -354,6 +354,7 @@ module ActiveStorage
354
354
  mattr_accessor :unsupported_image_processing_arguments
355
355
 
356
356
  mattr_accessor :service_urls_expire_in, default: 5.minutes
357
+ mattr_accessor :touch_attachment_records, default: true
357
358
  mattr_accessor :urls_expire_in
358
359
 
359
360
  mattr_accessor :routes_prefix, default: "/rails/active_storage"
@@ -364,22 +365,6 @@ module ActiveStorage
364
365
 
365
366
  mattr_accessor :video_preview_arguments, default: "-y -vframes 1 -f image2"
366
367
 
367
- def self.replace_on_assign_to_many
368
- ActiveStorage.deprecator.warn("config.active_storage.replace_on_assign_to_many is deprecated and has no effect.")
369
- end
370
-
371
- def self.replace_on_assign_to_many=(value)
372
- ActiveStorage.deprecator.warn("config.active_storage.replace_on_assign_to_many is deprecated and has no effect.")
373
- end
374
-
375
- def self.silence_invalid_content_types_warning
376
- ActiveStorage.deprecator.warn("config.active_storage.silence_invalid_content_types_warning is deprecated and has no effect.")
377
- end
378
-
379
- def self.silence_invalid_content_types_warning=(value)
380
- ActiveStorage.deprecator.warn("config.active_storage.silence_invalid_content_types_warning is deprecated and has no effect.")
381
- end
382
-
383
368
  module Transformers
384
369
  extend ActiveSupport::Autoload
385
370
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activestorage
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.1.0
4
+ version: 7.2.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-05 00:00:00.000000000 Z
11
+ date: 2024-12-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,56 +16,56 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 7.1.0
19
+ version: 7.2.2.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 7.1.0
26
+ version: 7.2.2.1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: actionpack
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 7.1.0
33
+ version: 7.2.2.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 7.1.0
40
+ version: 7.2.2.1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: activejob
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - '='
46
46
  - !ruby/object:Gem::Version
47
- version: 7.1.0
47
+ version: 7.2.2.1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - '='
53
53
  - !ruby/object:Gem::Version
54
- version: 7.1.0
54
+ version: 7.2.2.1
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: activerecord
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: 7.1.0
61
+ version: 7.2.2.1
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - '='
67
67
  - !ruby/object:Gem::Version
68
- version: 7.1.0
68
+ version: 7.2.2.1
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: marcel
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -116,6 +116,7 @@ files:
116
116
  - app/jobs/active_storage/analyze_job.rb
117
117
  - app/jobs/active_storage/base_job.rb
118
118
  - app/jobs/active_storage/mirror_job.rb
119
+ - app/jobs/active_storage/preview_image_job.rb
119
120
  - app/jobs/active_storage/purge_job.rb
120
121
  - app/jobs/active_storage/transform_job.rb
121
122
  - app/models/active_storage/attachment.rb
@@ -123,6 +124,7 @@ files:
123
124
  - app/models/active_storage/blob/analyzable.rb
124
125
  - app/models/active_storage/blob/identifiable.rb
125
126
  - app/models/active_storage/blob/representable.rb
127
+ - app/models/active_storage/blob/servable.rb
126
128
  - app/models/active_storage/current.rb
127
129
  - app/models/active_storage/filename.rb
128
130
  - app/models/active_storage/named_variant.rb
@@ -188,12 +190,12 @@ licenses:
188
190
  - MIT
189
191
  metadata:
190
192
  bug_tracker_uri: https://github.com/rails/rails/issues
191
- changelog_uri: https://github.com/rails/rails/blob/v7.1.0/activestorage/CHANGELOG.md
192
- documentation_uri: https://api.rubyonrails.org/v7.1.0/
193
+ changelog_uri: https://github.com/rails/rails/blob/v7.2.2.1/activestorage/CHANGELOG.md
194
+ documentation_uri: https://api.rubyonrails.org/v7.2.2.1/
193
195
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
194
- source_code_uri: https://github.com/rails/rails/tree/v7.1.0/activestorage
196
+ source_code_uri: https://github.com/rails/rails/tree/v7.2.2.1/activestorage
195
197
  rubygems_mfa_required: 'true'
196
- post_install_message:
198
+ post_install_message:
197
199
  rdoc_options: []
198
200
  require_paths:
199
201
  - lib
@@ -201,15 +203,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
201
203
  requirements:
202
204
  - - ">="
203
205
  - !ruby/object:Gem::Version
204
- version: 2.7.0
206
+ version: 3.1.0
205
207
  required_rubygems_version: !ruby/object:Gem::Requirement
206
208
  requirements:
207
209
  - - ">="
208
210
  - !ruby/object:Gem::Version
209
211
  version: '0'
210
212
  requirements: []
211
- rubygems_version: 3.4.18
212
- signing_key:
213
+ rubygems_version: 3.5.22
214
+ signing_key:
213
215
  specification_version: 4
214
216
  summary: Local and cloud file storage framework.
215
217
  test_files: []