activerecord 7.0.8.7 → 7.0.9

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.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

@@ -70,11 +70,13 @@ module ActiveRecord
70
70
  #
71
71
  # ==== Options
72
72
  #
73
- # +from+ When passed, this method will return false unless the original
74
- # value is equal to the given option
73
+ # [+from+]
74
+ # When specified, this method will return false unless the original
75
+ # value is equal to the given value.
75
76
  #
76
- # +to+ When passed, this method will return false unless the value was
77
- # changed to the given value
77
+ # [+to+]
78
+ # When specified, this method will return false unless the value will be
79
+ # changed to the given value.
78
80
  def saved_change_to_attribute?(attr_name, **options)
79
81
  mutations_before_last_save.changed?(attr_name.to_s, **options)
80
82
  end
@@ -120,11 +122,13 @@ module ActiveRecord
120
122
  #
121
123
  # ==== Options
122
124
  #
123
- # +from+ When passed, this method will return false unless the original
124
- # value is equal to the given option
125
+ # [+from+]
126
+ # When specified, this method will return false unless the original
127
+ # value is equal to the given value.
125
128
  #
126
- # +to+ When passed, this method will return false unless the value will be
127
- # changed to the given value
129
+ # [+to+]
130
+ # When specified, this method will return false unless the value will be
131
+ # changed to the given value.
128
132
  def will_save_change_to_attribute?(attr_name, **options)
129
133
  mutations_from_database.changed?(attr_name.to_s, **options)
130
134
  end
@@ -448,8 +448,7 @@ module ActiveRecord
448
448
  @available.num_waiting
449
449
  end
450
450
 
451
- # Return connection pool's usage statistic
452
- # Example:
451
+ # Returns the connection pool's usage statistic.
453
452
  #
454
453
  # ActiveRecord::Base.connection_pool.stat # => { size: 15, connections: 1, busy: 1, dead: 0, idle: 0, waiting: 0, checkout_timeout: 5 }
455
454
  def stat
@@ -653,9 +652,14 @@ module ActiveRecord
653
652
  alias_method :release, :remove_connection_from_thread_cache
654
653
 
655
654
  def new_connection
656
- Base.public_send(db_config.adapter_method, db_config.configuration_hash).tap do |conn|
655
+ conn = Base.public_send(db_config.adapter_method, db_config.configuration_hash)
656
+ begin
657
657
  conn.check_version
658
+ rescue
659
+ conn.disconnect!
660
+ raise
658
661
  end
662
+ conn
659
663
  end
660
664
 
661
665
  # If the pool is not at a <tt>@size</tt> limit, establish new connection. Connecting
@@ -941,7 +941,6 @@ module ActiveRecord
941
941
  # Adds a reference. The reference column is a bigint by default,
942
942
  # the <tt>:type</tt> option can be used to specify a different type.
943
943
  # Optionally adds a +_type+ column, if <tt>:polymorphic</tt> option is provided.
944
- # #add_reference and #add_belongs_to are acceptable.
945
944
  #
946
945
  # The +options+ hash can include the following keys:
947
946
  # [<tt>:type</tt>]
@@ -992,7 +991,6 @@ module ActiveRecord
992
991
  alias :add_belongs_to :add_reference
993
992
 
994
993
  # Removes the reference(s). Also removes a +type+ column if one exists.
995
- # #remove_reference and #remove_belongs_to are acceptable.
996
994
  #
997
995
  # ====== Remove the reference
998
996
  #
@@ -435,6 +435,13 @@ module ActiveRecord
435
435
  expression = row["expression"]
436
436
  expression = expression[1..-2] if expression.start_with?("(") && expression.end_with?(")")
437
437
  expression = strip_whitespace_characters(expression)
438
+
439
+ unless mariadb?
440
+ # MySQL returns check constraints expression in an already escaped form.
441
+ # This leads to duplicate escaping later (e.g. when the expression is used in the SchemaDumper).
442
+ expression = expression.gsub("\\'", "'")
443
+ end
444
+
438
445
  CheckConstraintDefinition.new(table_name, expression, options)
439
446
  end
440
447
  else
@@ -36,7 +36,7 @@ module ActiveRecord
36
36
  end
37
37
 
38
38
  if row[:Expression]
39
- expression = row[:Expression]
39
+ expression = row[:Expression].gsub("\\'", "'")
40
40
  expression = +"(#{expression})" unless expression.start_with?("(")
41
41
  indexes.last[-2] << expression
42
42
  indexes.last[-1][:expressions] ||= {}
@@ -181,6 +181,7 @@ module ActiveRecord
181
181
  default, default_function = nil, default
182
182
  elsif type_metadata.extra == "DEFAULT_GENERATED"
183
183
  default = +"(#{default})" unless default.start_with?("(")
184
+ default = default.gsub("\\'", "'")
184
185
  default, default_function = nil, default
185
186
  elsif type_metadata.type == :text && default&.start_with?("'")
186
187
  # strip and unescape quotes
@@ -27,9 +27,10 @@ module ActiveRecord
27
27
  value = value.sub(/^\((.+)\)$/, '-\1') # (4)
28
28
  case value
29
29
  when /^-?\D*+[\d,]+\.\d{2}$/ # (1)
30
- value.gsub!(/[^-\d.]/, "")
30
+ value.delete!("^-0-9.")
31
31
  when /^-?\D*+[\d.]+,\d{2}$/ # (2)
32
- value.gsub!(/[^-\d,]/, "").sub!(/,/, ".")
32
+ value.delete!("^-0-9,")
33
+ value.tr!(",", ".")
33
34
  end
34
35
 
35
36
  super(value)
@@ -339,7 +339,7 @@ module ActiveRecord
339
339
  JOIN pg_namespace nsp ON (t.relnamespace = nsp.oid)
340
340
  WHERE t.oid = #{quote(quote_table_name(table))}::regclass
341
341
  AND cons.contype = 'p'
342
- AND pg_get_expr(def.adbin, def.adrelid) ~* 'nextval|uuid_generate'
342
+ AND pg_get_expr(def.adbin, def.adrelid) ~* 'nextval|uuid_generate|gen_random_uuid'
343
343
  SQL
344
344
  end
345
345
 
@@ -282,7 +282,7 @@ module ActiveRecord
282
282
 
283
283
  attr_writer :connection_specification_name
284
284
 
285
- # Return the connection specification name from the current class or its parent.
285
+ # Returns the connection specification name from the current class or its parent.
286
286
  def connection_specification_name
287
287
  if !defined?(@connection_specification_name) || @connection_specification_name.nil?
288
288
  return self == Base ? Base.name : superclass.connection_specification_name
@@ -14,9 +14,10 @@ module ActiveRecord
14
14
  ##
15
15
  # :singleton-method:
16
16
  #
17
- # Accepts a logger conforming to the interface of Log4r which is then
18
- # passed on to any new database connections made and which can be
19
- # retrieved on both a class and instance level by calling +logger+.
17
+ # Accepts a logger conforming to the interface of Log4r or the default
18
+ # Ruby +Logger+ class, which is then passed on to any new database
19
+ # connections made. You can retrieve this logger by calling +logger+ on
20
+ # either an Active Record model class or an Active Record model instance.
20
21
  class_attribute :logger, instance_writer: false
21
22
 
22
23
  ##
@@ -117,7 +118,7 @@ module ActiveRecord
117
118
  The new connection handling does not support `connection_handlers`
118
119
  getter and setter.
119
120
 
120
- Read more about how to migrate at: https://guides.rubyonrails.org/active_record_multiple_databases.html#migrate-to-the-new-connection-handling
121
+ Read more about how to migrate at: https://guides.rubyonrails.org/v7.0/active_record_multiple_databases.html#migrate-to-the-new-connection-handling
121
122
  MSG
122
123
  else
123
124
  raise NotImplementedError, "The new connection handling does not support multiple connection handlers."
@@ -102,14 +102,14 @@ module ActiveRecord
102
102
  # You create a new record that uses delegated typing by creating the delegator and delegatee at the same time,
103
103
  # like so:
104
104
  #
105
- # Entry.create! entryable: Comment.new(content: "Hello!"), creator: Current.user
105
+ # Entry.create! entryable: Comment.new(content: "Hello!"), creator: Current.user, account: Current.account
106
106
  #
107
107
  # If you need more complicated composition, or you need to perform dependent validation, you should build a factory
108
108
  # method or class to take care of the complicated needs. This could be as simple as:
109
109
  #
110
110
  # class Entry < ApplicationRecord
111
- # def self.create_with_comment(content, creator: Current.user)
112
- # create! entryable: Comment.new(content: content), creator: creator
111
+ # def self.create_with_comment(content, creator: Current.user, account: Current.account)
112
+ # create! entryable: Comment.new(content: content), creator: creator, account: account
113
113
  # end
114
114
  # end
115
115
  #
@@ -35,85 +35,71 @@ module ActiveRecord
35
35
  ActiveRecord::Relation.prepend(RelationQueries)
36
36
  ActiveRecord::Base.include(CoreQueries)
37
37
  ActiveRecord::Encryption::EncryptedAttributeType.prepend(ExtendedEncryptableType)
38
- Arel::Nodes::HomogeneousIn.prepend(InWithAdditionalValues)
39
38
  end
40
39
 
41
- module EncryptedQueryArgumentProcessor
42
- extend ActiveSupport::Concern
40
+ module EncryptedQuery # :nodoc:
41
+ class << self
42
+ def process_arguments(owner, args, check_for_additional_values)
43
+ return args if owner.deterministic_encrypted_attributes&.empty?
43
44
 
44
- private
45
- def process_encrypted_query_arguments(args, check_for_additional_values)
46
45
  if args.is_a?(Array) && (options = args.first).is_a?(Hash)
47
- self.deterministic_encrypted_attributes&.each do |attribute_name|
48
- type = type_for_attribute(attribute_name)
46
+ options = options.dup
47
+ args[0] = options
48
+
49
+ owner.deterministic_encrypted_attributes&.each do |attribute_name|
50
+ type = owner.type_for_attribute(attribute_name)
49
51
  if !type.previous_types.empty? && value = options[attribute_name]
50
52
  options[attribute_name] = process_encrypted_query_argument(value, check_for_additional_values, type)
51
53
  end
52
54
  end
53
55
  end
56
+
57
+ args
54
58
  end
55
59
 
56
- def process_encrypted_query_argument(value, check_for_additional_values, type)
57
- return value if check_for_additional_values && value.is_a?(Array) && value.last.is_a?(AdditionalValue)
58
-
59
- case value
60
- when String, Array
61
- list = Array(value)
62
- list + list.flat_map do |each_value|
63
- if check_for_additional_values && each_value.is_a?(AdditionalValue)
64
- each_value
65
- else
66
- additional_values_for(each_value, type)
60
+ private
61
+ def process_encrypted_query_argument(value, check_for_additional_values, type)
62
+ return value if check_for_additional_values && value.is_a?(Array) && value.last.is_a?(AdditionalValue)
63
+
64
+ case value
65
+ when String, Array
66
+ list = Array(value)
67
+ list + list.flat_map do |each_value|
68
+ if check_for_additional_values && each_value.is_a?(AdditionalValue)
69
+ each_value
70
+ else
71
+ additional_values_for(each_value, type)
72
+ end
67
73
  end
74
+ else
75
+ value
68
76
  end
69
- else
70
- value
71
77
  end
72
- end
73
78
 
74
- def additional_values_for(value, type)
75
- type.previous_types.collect do |additional_type|
76
- AdditionalValue.new(value, additional_type)
79
+ def additional_values_for(value, type)
80
+ type.previous_types.collect do |additional_type|
81
+ AdditionalValue.new(value, additional_type)
82
+ end
77
83
  end
78
- end
84
+ end
79
85
  end
80
86
 
81
87
  module RelationQueries
82
- include EncryptedQueryArgumentProcessor
83
-
84
88
  def where(*args)
85
- process_encrypted_query_arguments_if_needed(args)
86
- super
89
+ super(*EncryptedQuery.process_arguments(self, args, true))
87
90
  end
88
91
 
89
92
  def exists?(*args)
90
- process_encrypted_query_arguments_if_needed(args)
91
- super
92
- end
93
-
94
- def find_or_create_by(attributes, &block)
95
- find_by(attributes.dup) || create(attributes, &block)
96
- end
97
-
98
- def find_or_create_by!(attributes, &block)
99
- find_by(attributes.dup) || create!(attributes, &block)
93
+ super(*EncryptedQuery.process_arguments(self, args, true))
100
94
  end
101
-
102
- private
103
- def process_encrypted_query_arguments_if_needed(args)
104
- process_encrypted_query_arguments(args, true) unless self.deterministic_encrypted_attributes&.empty?
105
- end
106
95
  end
107
96
 
108
97
  module CoreQueries
109
98
  extend ActiveSupport::Concern
110
99
 
111
100
  class_methods do
112
- include EncryptedQueryArgumentProcessor
113
-
114
101
  def find_by(*args)
115
- process_encrypted_query_arguments(args, false) unless self.deterministic_encrypted_attributes&.empty?
116
- super
102
+ super(*EncryptedQuery.process_arguments(self, args, false))
117
103
  end
118
104
  end
119
105
  end
@@ -141,20 +127,6 @@ module ActiveRecord
141
127
  end
142
128
  end
143
129
  end
144
-
145
- module InWithAdditionalValues
146
- def proc_for_binds
147
- -> value { ActiveModel::Attribute.with_cast_value(attribute.name, value, encryption_aware_type_caster) }
148
- end
149
-
150
- def encryption_aware_type_caster
151
- if attribute.type_caster.is_a?(ActiveRecord::Encryption::EncryptedAttributeType)
152
- attribute.type_caster.cast_type
153
- else
154
- attribute.type_caster
155
- end
156
- end
157
- end
158
130
  end
159
131
  end
160
132
  end
@@ -258,6 +258,8 @@ module ActiveRecord
258
258
  # name: Reginald the Pirate
259
259
  # monkey_id: 1
260
260
  #
261
+ # <code></code>
262
+ #
261
263
  # ### in monkeys.yml
262
264
  #
263
265
  # george:
@@ -275,6 +277,8 @@ module ActiveRecord
275
277
  # name: Reginald the Pirate
276
278
  # monkey: george
277
279
  #
280
+ # <code></code>
281
+ #
278
282
  # ### in monkeys.yml
279
283
  #
280
284
  # george:
@@ -296,6 +300,8 @@ module ActiveRecord
296
300
  #
297
301
  # belongs_to :eater, polymorphic: true
298
302
  #
303
+ # <code></code>
304
+ #
299
305
  # ### in fruits.yml
300
306
  #
301
307
  # apple:
@@ -321,6 +327,8 @@ module ActiveRecord
321
327
  # id: 1
322
328
  # name: George the Monkey
323
329
  #
330
+ # <code></code>
331
+ #
324
332
  # ### in fruits.yml
325
333
  #
326
334
  # apple:
@@ -335,6 +343,8 @@ module ActiveRecord
335
343
  # id: 3
336
344
  # name: grape
337
345
  #
346
+ # <code></code>
347
+ #
338
348
  # ### in fruits_monkeys.yml
339
349
  #
340
350
  # apple_george:
@@ -358,6 +368,8 @@ module ActiveRecord
358
368
  # name: George the Monkey
359
369
  # fruits: apple, orange, grape
360
370
  #
371
+ # <code></code>
372
+ #
361
373
  # ### in fruits.yml
362
374
  #
363
375
  # apple:
@@ -9,8 +9,8 @@ module ActiveRecord
9
9
  module VERSION
10
10
  MAJOR = 7
11
11
  MINOR = 0
12
- TINY = 8
13
- PRE = "7"
12
+ TINY = 9
13
+ PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -17,8 +17,6 @@ module ActiveRecord
17
17
  disallow_raw_sql!(on_duplicate)
18
18
  disallow_raw_sql!(returning)
19
19
 
20
- configure_on_duplicate_update_logic
21
-
22
20
  if model.scope_attributes?
23
21
  @scope_attributes = model.scope_attributes
24
22
  @keys |= @scope_attributes.keys
@@ -29,8 +27,8 @@ module ActiveRecord
29
27
  @returning = false if @returning == []
30
28
 
31
29
  @unique_by = find_unique_index_for(unique_by)
32
- @on_duplicate = :skip if @on_duplicate == :update && updatable_columns.empty?
33
30
 
31
+ configure_on_duplicate_update_logic
34
32
  ensure_valid_options_for_connection!
35
33
  end
36
34
 
@@ -99,6 +97,8 @@ module ActiveRecord
99
97
  elsif custom_update_sql_provided?
100
98
  @update_sql = on_duplicate
101
99
  @on_duplicate = :update
100
+ elsif @on_duplicate == :update && updatable_columns.empty?
101
+ @on_duplicate = :skip
102
102
  end
103
103
  end
104
104
 
@@ -22,7 +22,7 @@ module ActiveRecord
22
22
  # To use the DatabaseSelector in your application with default settings,
23
23
  # run the provided generator.
24
24
  #
25
- # bin/rails g active_record:multi_db
25
+ # $ bin/rails g active_record:multi_db
26
26
  #
27
27
  # This will create a file named +config/initializers/multi_db.rb+ with the
28
28
  # following contents:
@@ -364,7 +364,8 @@ module ActiveRecord
364
364
  # The Rails package has several tools to help create and apply migrations.
365
365
  #
366
366
  # To generate a new migration, you can use
367
- # bin/rails generate migration MyNewMigration
367
+ #
368
+ # $ bin/rails generate migration MyNewMigration
368
369
  #
369
370
  # where MyNewMigration is the name of your migration. The generator will
370
371
  # create an empty migration file <tt>timestamp_my_new_migration.rb</tt>
@@ -373,7 +374,7 @@ module ActiveRecord
373
374
  #
374
375
  # There is a special syntactic shortcut to generate migrations that add fields to a table.
375
376
  #
376
- # bin/rails generate migration add_fieldname_to_tablename fieldname:string
377
+ # $ bin/rails generate migration add_fieldname_to_tablename fieldname:string
377
378
  #
378
379
  # This will generate the file <tt>timestamp_add_fieldname_to_tablename.rb</tt>, which will look like this:
379
380
  # class AddFieldnameToTablename < ActiveRecord::Migration[7.0]
@@ -276,8 +276,10 @@ module ActiveRecord
276
276
 
277
277
  # Computes the table name, (re)sets it internally, and returns it.
278
278
  def reset_table_name # :nodoc:
279
- self.table_name = if abstract_class?
280
- superclass == Base ? nil : superclass.table_name
279
+ self.table_name = if self == Base
280
+ nil
281
+ elsif abstract_class?
282
+ superclass.table_name
281
283
  elsif superclass.abstract_class?
282
284
  superclass.table_name || compute_table_name
283
285
  else
@@ -457,7 +459,7 @@ module ActiveRecord
457
459
  end
458
460
 
459
461
  # Returns the column object for the named attribute.
460
- # Returns an +ActiveRecord::ConnectionAdapters::NullColumn+ if the
462
+ # Returns an ActiveRecord::ConnectionAdapters::NullColumn if the
461
463
  # named attribute does not exist.
462
464
  #
463
465
  # class Person < ActiveRecord::Base
@@ -289,7 +289,7 @@ module ActiveRecord
289
289
  # [:allow_destroy]
290
290
  # If true, destroys any members from the attributes hash with a
291
291
  # <tt>_destroy</tt> key and a value that evaluates to +true+
292
- # (e.g. 1, '1', true, or 'true'). This option is off by default.
292
+ # (e.g. 1, '1', true, or 'true'). This option is false by default.
293
293
  # [:reject_if]
294
294
  # Allows you to specify a Proc or a Symbol pointing to a method
295
295
  # that checks whether a record should be built for a certain attribute
@@ -314,11 +314,11 @@ module ActiveRecord
314
314
  # nested attributes are going to be used when an associated record already
315
315
  # exists. In general, an existing record may either be updated with the
316
316
  # new set of attribute values or be replaced by a wholly new record
317
- # containing those values. By default the +:update_only+ option is +false+
317
+ # containing those values. By default the +:update_only+ option is false
318
318
  # and the nested attributes are used to update the existing record only
319
319
  # if they include the record's <tt>:id</tt> value. Otherwise a new
320
320
  # record will be instantiated and used to replace the existing one.
321
- # However if the +:update_only+ option is +true+, the nested attributes
321
+ # However if the +:update_only+ option is true, the nested attributes
322
322
  # are used to update the record's attributes always, regardless of
323
323
  # whether the <tt>:id</tt> is present. The option is ignored for collection
324
324
  # associations.
@@ -343,7 +343,7 @@ To keep using the current cache store, you can turn off cache versioning entirel
343
343
  end
344
344
 
345
345
  ActiveSupport.on_load(:active_record_fixture_set) do
346
- # Encrypt active record fixtures
346
+ # Encrypt Active Record fixtures
347
347
  if ActiveRecord::Encryption.config.encrypt_fixtures
348
348
  ActiveRecord::Fixture.prepend ActiveRecord::Encryption::EncryptedFixtures
349
349
  end
@@ -90,7 +90,7 @@ module ActiveRecord
90
90
  :to_sentence, :to_fs, :to_formatted_s, :as_json,
91
91
  :shuffle, :split, :slice, :index, :rindex, to: :records
92
92
 
93
- delegate :primary_key, :connection, to: :klass
93
+ delegate :primary_key, :connection, :transaction, to: :klass
94
94
 
95
95
  module ClassSpecificRelation # :nodoc:
96
96
  extend ActiveSupport::Concern
@@ -43,7 +43,7 @@ module ActiveRecord
43
43
  def bind_attribute(name, value) # :nodoc:
44
44
  if reflection = klass._reflect_on_association(name)
45
45
  name = reflection.foreign_key
46
- value = value.read_attribute(reflection.klass.primary_key) unless value.nil?
46
+ value = value.read_attribute(reflection.association_primary_key) unless value.nil?
47
47
  end
48
48
 
49
49
  attr = table[name]
@@ -30,7 +30,7 @@ module ActiveRecord
30
30
  #
31
31
  # ActiveRecord::Base.time_zone_aware_types = [:datetime]
32
32
  #
33
- # You can also add database specific timezone aware types. For example, for PostgreSQL:
33
+ # You can also add database-specific timezone aware types. For example, for PostgreSQL:
34
34
  #
35
35
  # ActiveRecord::Base.time_zone_aware_types += [:tsrange, :tstzrange]
36
36
  #
@@ -56,7 +56,7 @@ module Arel # :nodoc: all
56
56
  end
57
57
 
58
58
  def proc_for_binds
59
- -> value { ActiveModel::Attribute.with_cast_value(attribute.name, value, attribute.type_caster) }
59
+ -> value { ActiveModel::Attribute.with_cast_value(attribute.name, value, ActiveModel::Type.default_value) }
60
60
  end
61
61
 
62
62
  def fetch_attribute(&block)
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.8.7
4
+ version: 7.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-12-10 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activesupport
@@ -16,28 +15,28 @@ dependencies:
16
15
  requirements:
17
16
  - - '='
18
17
  - !ruby/object:Gem::Version
19
- version: 7.0.8.7
18
+ version: 7.0.9
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - '='
25
24
  - !ruby/object:Gem::Version
26
- version: 7.0.8.7
25
+ version: 7.0.9
27
26
  - !ruby/object:Gem::Dependency
28
27
  name: activemodel
29
28
  requirement: !ruby/object:Gem::Requirement
30
29
  requirements:
31
30
  - - '='
32
31
  - !ruby/object:Gem::Version
33
- version: 7.0.8.7
32
+ version: 7.0.9
34
33
  type: :runtime
35
34
  prerelease: false
36
35
  version_requirements: !ruby/object:Gem::Requirement
37
36
  requirements:
38
37
  - - '='
39
38
  - !ruby/object:Gem::Version
40
- version: 7.0.8.7
39
+ version: 7.0.9
41
40
  description: Databases on Rails. Build a persistent domain model by mapping database
42
41
  tables to Ruby classes. Strong conventions for associations, validations, aggregations,
43
42
  migrations, and testing come baked-in.
@@ -434,12 +433,11 @@ licenses:
434
433
  - MIT
435
434
  metadata:
436
435
  bug_tracker_uri: https://github.com/rails/rails/issues
437
- changelog_uri: https://github.com/rails/rails/blob/v7.0.8.7/activerecord/CHANGELOG.md
438
- documentation_uri: https://api.rubyonrails.org/v7.0.8.7/
436
+ changelog_uri: https://github.com/rails/rails/blob/v7.0.9/activerecord/CHANGELOG.md
437
+ documentation_uri: https://api.rubyonrails.org/v7.0.9/
439
438
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
440
- source_code_uri: https://github.com/rails/rails/tree/v7.0.8.7/activerecord
439
+ source_code_uri: https://github.com/rails/rails/tree/v7.0.9/activerecord
441
440
  rubygems_mfa_required: 'true'
442
- post_install_message:
443
441
  rdoc_options:
444
442
  - "--main"
445
443
  - README.rdoc
@@ -456,8 +454,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
456
454
  - !ruby/object:Gem::Version
457
455
  version: '0'
458
456
  requirements: []
459
- rubygems_version: 3.5.22
460
- signing_key:
457
+ rubygems_version: 3.6.9
461
458
  specification_version: 4
462
459
  summary: Object-relational mapper framework (part of Rails).
463
460
  test_files: []