activerecord 7.0.5 → 7.0.8.6

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.

Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +215 -1
  3. data/README.rdoc +2 -2
  4. data/lib/active_record/associations/collection_association.rb +1 -1
  5. data/lib/active_record/associations/collection_proxy.rb +5 -0
  6. data/lib/active_record/associations/has_one_association.rb +0 -4
  7. data/lib/active_record/associations/singular_association.rb +5 -7
  8. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1 -1
  9. data/lib/active_record/connection_adapters/abstract_adapter.rb +0 -17
  10. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +8 -6
  11. data/lib/active_record/connection_adapters/mysql/database_statements.rb +1 -1
  12. data/lib/active_record/connection_adapters/mysql/quoting.rb +5 -2
  13. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +1 -1
  14. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +1 -1
  15. data/lib/active_record/connection_adapters/postgresql/quoting.rb +5 -2
  16. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +5 -2
  17. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -0
  18. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +2 -2
  19. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +2 -4
  20. data/lib/active_record/gem_version.rb +2 -2
  21. data/lib/active_record/locking/optimistic.rb +32 -18
  22. data/lib/active_record/migration/compatibility.rb +12 -54
  23. data/lib/active_record/migration.rb +52 -3
  24. data/lib/active_record/persistence.rb +7 -5
  25. data/lib/active_record/railties/controller_runtime.rb +3 -4
  26. data/lib/active_record/reflection.rb +8 -0
  27. data/lib/active_record/relation/predicate_builder/association_query_value.rb +20 -1
  28. data/lib/active_record/relation/predicate_builder.rb +1 -2
  29. data/lib/active_record/relation/query_attribute.rb +23 -0
  30. data/lib/active_record/relation/query_methods.rb +34 -7
  31. data/lib/active_record/result.rb +6 -4
  32. data/lib/active_record/table_metadata.rb +6 -2
  33. data/lib/active_record/transactions.rb +3 -3
  34. data/lib/active_record/type/serialized.rb +4 -0
  35. data/lib/arel/nodes/and.rb +4 -0
  36. metadata +10 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f3039efb205667bcd9fc218b22042ee4a8f36b735f62fedf208a56b70bb3bd5c
4
- data.tar.gz: df54f94c2480c583f2236f31de29f55525ee8f281fea93b30690f57f775d758b
3
+ metadata.gz: d0dafed5cde1fc09899d9caea484b616eee6a654c8cdc2a4980900466a8e2ed5
4
+ data.tar.gz: 7a70971a3a00e75b2c1cce9c7e139a6eef609d0f3b650418ddf93c242e4539f0
5
5
  SHA512:
6
- metadata.gz: a412b99cef7bb68b569f14be355f715f888f0072f33436d40ffe8e4c90c088539d0fd1d26d43e508d5e6a2089ad7a73874f1aef7094bc7dc5287bccca753496b
7
- data.tar.gz: 4b6008f67510a941efad31e7cddc4f6af2a7149da4a68cb248ce5481631c674216204d0a0028686c36a8f61f4366b1b2c096c5a6fd8ea61d29884bc57822a0fe
6
+ metadata.gz: 770556493365d077a3bd6b825f2f1f68c7b2b124908ba8e5efd264d97f0ea7735c9594654017fb13d501d7e1818bf3a4d6e1435ce93e9081a39bae6f1d59851c
7
+ data.tar.gz: 30ddf2ad9e7eed26fe0ff9e453a7e201bd576ea0f0564dfded84333f4527e093f61b44fb02b2aedd4b2676354ba18e334ac17146b26ded1a6bbabda47d35221f
data/CHANGELOG.md CHANGED
@@ -1,3 +1,217 @@
1
+ ## Rails 7.0.8.6 (October 23, 2024) ##
2
+
3
+ * No changes.
4
+
5
+
6
+ ## Rails 7.0.8.5 (October 15, 2024) ##
7
+
8
+ * No changes.
9
+
10
+
11
+ ## Rails 7.0.8.4 (June 04, 2024) ##
12
+
13
+ * No changes.
14
+
15
+
16
+ ## Rails 7.0.8.3 (May 17, 2024) ##
17
+
18
+ * No changes.
19
+
20
+
21
+ ## Rails 7.0.8.2 (May 16, 2024) ##
22
+
23
+ * No changes.
24
+
25
+
26
+ ## Rails 7.0.8.1 (February 21, 2024) ##
27
+
28
+ * No changes.
29
+
30
+
31
+ ## Rails 7.0.8 (September 09, 2023) ##
32
+
33
+ * Fix `change_column` not setting `precision: 6` on `datetime` columns when
34
+ using 7.0+ Migrations and SQLite.
35
+
36
+ *Hartley McGuire*
37
+
38
+ * Fix unscope is not working in specific case
39
+
40
+ Before:
41
+ ```ruby
42
+ Post.where(id: 1...3).unscope(where: :id).to_sql # "SELECT `posts`.* FROM `posts` WHERE `posts`.`id` >= 1 AND `posts`.`id` < 3"
43
+
44
+ ```
45
+
46
+ After:
47
+ ```ruby
48
+ Post.where(id: 1...3).unscope(where: :id).to_sql # "SELECT `posts`.* FROM `posts`"
49
+ ```
50
+
51
+ Fixes #48094.
52
+
53
+ *Kazuya Hatanaka*
54
+
55
+ * Fix associations to a STI model including a `class_name` parameter
56
+
57
+ ```ruby
58
+ class Product < ApplicationRecord
59
+ has_many :requests, as: :requestable, class_name: "ProductRequest", dependent: :destroy
60
+ end
61
+
62
+ # STI tables
63
+ class Request < ApplicationRecord
64
+ belongs_to :requestable, polymorphic: true
65
+
66
+ validate :request_type, presence: true
67
+ end
68
+
69
+ class ProductRequest < Request
70
+ belongs_to :user
71
+ end
72
+ ```
73
+
74
+ Accessing such association would lead to:
75
+
76
+ ```
77
+ table_metadata.rb:22:in `has_column?': undefined method `key?' for nil:NilClass (NoMethodError)
78
+ ```
79
+
80
+ *Romain Filinto*
81
+
82
+ * Fix `change_table` setting datetime precision for 6.1 Migrations
83
+
84
+ *Hartley McGuire*
85
+
86
+ * Fix change_column setting datetime precision for 6.1 Migrations
87
+
88
+ *Hartley McGuire*
89
+
90
+ ## Rails 7.0.7.2 (August 22, 2023) ##
91
+
92
+ * No changes.
93
+
94
+
95
+ ## Rails 7.0.7.1 (August 22, 2023) ##
96
+
97
+ * No changes.
98
+
99
+
100
+ ## Rails 7.0.7 (August 09, 2023) ##
101
+
102
+ * Restores functionality to the missing method when using enums and fixes.
103
+
104
+ *paulreece*
105
+
106
+ * Fix `StatementCache::Substitute` with serialized type.
107
+
108
+ *ywenc*
109
+
110
+ * Fix `:db_runtime` on notification payload when application have multiple databases.
111
+
112
+ *Eileen M. Uchitelle*
113
+
114
+ * Correctly dump check constraints for MySQL 8.0.16+.
115
+
116
+ *Steve Hill*
117
+
118
+ * Fix `ActiveRecord::QueryMethods#in_order_of` to include `nil`s, to match the
119
+ behavior of `Enumerable#in_order_of`.
120
+
121
+ For example, `Post.in_order_of(:title, [nil, "foo"])` will now include posts
122
+ with `nil` titles, the same as `Post.all.to_a.in_order_of(:title, [nil, "foo"])`.
123
+
124
+ *fatkodima*
125
+
126
+ * Revert "Fix autosave associations with validations added on `:base` of the associated objects."
127
+
128
+ This change intended to remove the :base attribute from the message,
129
+ but broke many assumptions which key these errors were stored.
130
+
131
+ *zzak*
132
+
133
+ * Fix `#previously_new_record?` to return true for destroyed records.
134
+
135
+ Before, if a record was created and then destroyed, `#previously_new_record?` would return true.
136
+ Now, any UPDATE or DELETE to a record is considered a change, and will result in `#previously_new_record?`
137
+ returning false.
138
+
139
+ *Adrianna Chang*
140
+
141
+ * Revert breaking changes to `has_one` relationship deleting the old record before the new one is validated.
142
+
143
+ *zzak*
144
+
145
+ * Fix support for Active Record instances being uses in queries.
146
+
147
+ As of `7.0.5`, query arguments were deep duped to avoid mutations impacting
148
+ the query cache, but this had the adverse effect to clearing the primary key when
149
+ the query argument contained an `ActiveRecord::Base` instance.
150
+
151
+ This broke the `noticed` gem.
152
+
153
+ *Jean Boussier*
154
+
155
+
156
+ ## Rails 7.0.6 (June 29, 2023) ##
157
+
158
+ * Fix autosave associations with validations added on `:base` of the associated objects.
159
+
160
+ *fatkodima*
161
+
162
+ * Fix result with anonymous PostgreSQL columns of different type from json.
163
+
164
+ *Oleksandr Avoiants*
165
+
166
+ * Preserve timestamp when setting an `ActiveSupport::TimeWithZone` value to `timestamptz` attribute.
167
+
168
+ *fatkodima*
169
+
170
+ * Fix assignment into an `has_one` relationship deleting the old record before the new one is validated.
171
+
172
+ *Jean Boussier*
173
+
174
+ * Fix where on association with has_one/has_many polymorphic relations.
175
+
176
+ Before:
177
+ ```ruby
178
+ Treasure.where(price_estimates: PriceEstimate.all)
179
+ #=> SELECT (...) WHERE "treasures"."id" IN (SELECT "price_estimates"."estimate_of_id" FROM "price_estimates")
180
+ ```
181
+
182
+ Later:
183
+ ```ruby
184
+ Treasure.where(price_estimates: PriceEstimate.all)
185
+ #=> SELECT (...) WHERE "treasures"."id" IN (SELECT "price_estimates"."estimate_of_id" FROM "price_estimates" WHERE "price_estimates"."estimate_of_type" = 'Treasure')
186
+ ```
187
+
188
+ *Lázaro Nixon*
189
+
190
+ * Fix decrementing counter caches on optimistically locked record deletion
191
+
192
+ *fatkodima*
193
+
194
+ * Ensure binary-destined values have binary encoding during type cast.
195
+
196
+ *Matthew Draper*
197
+
198
+ * Preserve existing column default functions when altering table in SQLite.
199
+
200
+ *fatkodima*
201
+
202
+ * Remove table alias added when using `where.missing` or `where.associated`.
203
+
204
+ *fatkodima*
205
+
206
+ * Fix `Enumerable#in_order_of` to only flatten first level to preserve nesting.
207
+
208
+ *Miha Rekar*
209
+
210
+
211
+ ## Rails 7.0.5.1 (June 26, 2023) ##
212
+
213
+ * No changes.
214
+
1
215
  ## Rails 7.0.5 (May 24, 2023) ##
2
216
 
3
217
  * Type cast `#attribute_changed?` `:from` and `:to` options.
@@ -76,7 +290,7 @@
76
290
 
77
291
  *Shota Toguchi*, *Yusaku Ono*
78
292
 
79
- * Use connection from `#with_raw_connection` in `#quote_string`.
293
+ * Fix erroneous nil default precision on virtual datetime columns.
80
294
 
81
295
  Prior to this change, virtual datetime columns did not have the same
82
296
  default precision as regular datetime columns, resulting in the following
data/README.rdoc CHANGED
@@ -192,7 +192,7 @@ The latest version of Active Record can be installed with RubyGems:
192
192
 
193
193
  $ gem install activerecord
194
194
 
195
- Source code can be downloaded as part of the Rails project on GitHub:
195
+ Source code can be downloaded as part of the \Rails project on GitHub:
196
196
 
197
197
  * https://github.com/rails/rails/tree/main/activerecord
198
198
 
@@ -210,7 +210,7 @@ API documentation is at:
210
210
 
211
211
  * https://api.rubyonrails.org
212
212
 
213
- Bug reports for the Ruby on Rails project can be filed here:
213
+ Bug reports for the Ruby on \Rails project can be filed here:
214
214
 
215
215
  * https://github.com/rails/rails/issues
216
216
 
@@ -79,7 +79,7 @@ module ActiveRecord
79
79
  def reset
80
80
  super
81
81
  @target = []
82
- @replaced_or_added_targets = Set.new
82
+ @replaced_or_added_targets = Set.new.compare_by_identity
83
83
  @association_ids = nil
84
84
  end
85
85
 
@@ -1102,6 +1102,11 @@ module ActiveRecord
1102
1102
  super
1103
1103
  end
1104
1104
 
1105
+ def pretty_print(pp) # :nodoc:
1106
+ load_target if find_from_target?
1107
+ super
1108
+ end
1109
+
1105
1110
  delegate_methods = [
1106
1111
  QueryMethods,
1107
1112
  SpawnMethods,
@@ -87,10 +87,6 @@ module ActiveRecord
87
87
  replace(record, false)
88
88
  end
89
89
 
90
- def replace_keys(record, force: false)
91
- # Has one association doesn't have foreign keys to replace.
92
- end
93
-
94
90
  def remove_target!(method)
95
91
  case method
96
92
  when :delete
@@ -54,13 +54,11 @@ module ActiveRecord
54
54
  end
55
55
 
56
56
  def _create_record(attributes, raise_error = false, &block)
57
- reflection.klass.transaction do
58
- record = build(attributes, &block)
59
- saved = record.save
60
- replace_keys(record, force: true)
61
- raise RecordInvalid.new(record) if !saved && raise_error
62
- record
63
- end
57
+ record = build_record(attributes, &block)
58
+ saved = record.save
59
+ set_new_record(record)
60
+ raise RecordInvalid.new(record) if !saved && raise_error
61
+ record
64
62
  end
65
63
  end
66
64
  end
@@ -264,7 +264,7 @@ module ActiveRecord
264
264
  #
265
265
  # generates:
266
266
  #
267
- # CREATE TABLE order (
267
+ # CREATE TABLE orders (
268
268
  # product_id bigint NOT NULL,
269
269
  # client_id bigint NOT NULL
270
270
  # );
@@ -71,14 +71,6 @@ module ActiveRecord
71
71
  /\A(?:[(\s]|#{COMMENT_REGEX})*#{Regexp.union(*parts)}/
72
72
  end
73
73
 
74
- def self.quoted_column_names # :nodoc:
75
- @quoted_column_names ||= {}
76
- end
77
-
78
- def self.quoted_table_names # :nodoc:
79
- @quoted_table_names ||= {}
80
- end
81
-
82
74
  def initialize(connection, logger = nil, config = {}) # :nodoc:
83
75
  super()
84
76
 
@@ -665,15 +657,6 @@ module ActiveRecord
665
657
  migration_context.current_version
666
658
  end
667
659
 
668
- def field_ordered_value(column, values) # :nodoc:
669
- node = Arel::Nodes::Case.new(column)
670
- values.each.with_index(1) do |value, order|
671
- node.when(value).then(order)
672
- end
673
-
674
- Arel::Nodes::Ascending.new(node.else(values.length + 1))
675
- end
676
-
677
660
  class << self
678
661
  private
679
662
  def initialize_type_map(m)
@@ -138,11 +138,6 @@ module ActiveRecord
138
138
  true
139
139
  end
140
140
 
141
- def field_ordered_value(column, values) # :nodoc:
142
- field = Arel::Nodes::NamedFunction.new("FIELD", [column, values.reverse.map { |value| Arel::Nodes.build_quoted(value) }])
143
- Arel::Nodes::Descending.new(field)
144
- end
145
-
146
141
  def get_advisory_lock(lock_name, timeout = 0) # :nodoc:
147
142
  query_value("SELECT GET_LOCK(#{quote(lock_name.to_s)}, #{timeout})") == 1
148
143
  end
@@ -438,7 +433,8 @@ module ActiveRecord
438
433
  name: row["name"]
439
434
  }
440
435
  expression = row["expression"]
441
- expression = expression[1..-2] unless mariadb? # remove parentheses added by mysql
436
+ expression = expression[1..-2] if expression.start_with?("(") && expression.end_with?(")")
437
+ expression = strip_whitespace_characters(expression)
442
438
  CheckConstraintDefinition.new(table_name, expression, options)
443
439
  end
444
440
  else
@@ -619,6 +615,12 @@ module ActiveRecord
619
615
  end
620
616
 
621
617
  private
618
+ def strip_whitespace_characters(expression)
619
+ expression = expression.gsub(/\\n|\\\\/, "")
620
+ expression = expression.gsub(/\s{2,}/, " ")
621
+ expression
622
+ end
623
+
622
624
  def text_type?(type)
623
625
  TYPE_MAP.lookup(type).is_a?(Type::String) || TYPE_MAP.lookup(type).is_a?(Type::Text)
624
626
  end
@@ -20,7 +20,7 @@ module ActiveRecord
20
20
  end
21
21
 
22
22
  READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
23
- :desc, :describe, :set, :show, :use
23
+ :desc, :describe, :set, :show, :use, :kill
24
24
  ) # :nodoc:
25
25
  private_constant :READ_QUERY
26
26
 
@@ -6,6 +6,9 @@ module ActiveRecord
6
6
  module ConnectionAdapters
7
7
  module MySQL
8
8
  module Quoting # :nodoc:
9
+ QUOTED_COLUMN_NAMES = Concurrent::Map.new # :nodoc:
10
+ QUOTED_TABLE_NAMES = Concurrent::Map.new # :nodoc:
11
+
9
12
  def quote_bound_value(value)
10
13
  case value
11
14
  when Rational
@@ -24,11 +27,11 @@ module ActiveRecord
24
27
  end
25
28
 
26
29
  def quote_column_name(name)
27
- self.class.quoted_column_names[name] ||= "`#{super.gsub('`', '``')}`"
30
+ QUOTED_COLUMN_NAMES[name] ||= "`#{super.gsub('`', '``')}`"
28
31
  end
29
32
 
30
33
  def quote_table_name(name)
31
- self.class.quoted_table_names[name] ||= super.gsub(".", "`.`").freeze
34
+ QUOTED_TABLE_NAMES[name] ||= super.gsub(".", "`.`").freeze
32
35
  end
33
36
 
34
37
  def unquoted_true
@@ -57,7 +57,7 @@ module ActiveRecord
57
57
  fields.each_with_index do |fname, i|
58
58
  ftype = result.ftype i
59
59
  fmod = result.fmod i
60
- types[fname] = get_oid_type(ftype, fmod, fname)
60
+ types[fname] = types[i] = get_oid_type(ftype, fmod, fname)
61
61
  end
62
62
  build_result(columns: fields, rows: result.values, column_types: types)
63
63
  end
@@ -13,7 +13,7 @@ module ActiveRecord
13
13
  return if value.blank?
14
14
 
15
15
  time = super
16
- return time unless time.acts_like?(:time)
16
+ return time if time.is_a?(ActiveSupport::TimeWithZone) || !time.acts_like?(:time)
17
17
 
18
18
  # While in UTC mode, the PG gem may not return times back in "UTC" even if they were provided to Postgres in UTC.
19
19
  # We prefer times always in UTC, so here we convert back.
@@ -4,6 +4,9 @@ module ActiveRecord
4
4
  module ConnectionAdapters
5
5
  module PostgreSQL
6
6
  module Quoting
7
+ QUOTED_COLUMN_NAMES = Concurrent::Map.new # :nodoc:
8
+ QUOTED_TABLE_NAMES = Concurrent::Map.new # :nodoc:
9
+
7
10
  class IntegerOutOf64BitRange < StandardError
8
11
  def initialize(msg)
9
12
  super(msg)
@@ -81,7 +84,7 @@ module ActiveRecord
81
84
  # - "schema.name".table_name
82
85
  # - "schema.name"."table.name"
83
86
  def quote_table_name(name) # :nodoc:
84
- self.class.quoted_table_names[name] ||= Utils.extract_schema_qualified_name(name.to_s).quoted.freeze
87
+ QUOTED_TABLE_NAMES[name] ||= Utils.extract_schema_qualified_name(name.to_s).quoted.freeze
85
88
  end
86
89
 
87
90
  # Quotes schema names for use in SQL queries.
@@ -95,7 +98,7 @@ module ActiveRecord
95
98
 
96
99
  # Quotes column names for use in SQL queries.
97
100
  def quote_column_name(name) # :nodoc:
98
- self.class.quoted_column_names[name] ||= PG::Connection.quote_ident(super).freeze
101
+ QUOTED_COLUMN_NAMES[name] ||= PG::Connection.quote_ident(super).freeze
99
102
  end
100
103
 
101
104
  # Quote date/time values for use in SQL input.
@@ -4,6 +4,9 @@ module ActiveRecord
4
4
  module ConnectionAdapters
5
5
  module SQLite3
6
6
  module Quoting # :nodoc:
7
+ QUOTED_COLUMN_NAMES = Concurrent::Map.new # :nodoc:
8
+ QUOTED_TABLE_NAMES = Concurrent::Map.new # :nodoc:
9
+
7
10
  def quote_string(s)
8
11
  @connection.class.quote(s)
9
12
  end
@@ -13,11 +16,11 @@ module ActiveRecord
13
16
  end
14
17
 
15
18
  def quote_table_name(name)
16
- self.class.quoted_table_names[name] ||= super.gsub(".", "\".\"").freeze
19
+ QUOTED_TABLE_NAMES[name] ||= super.gsub(".", "\".\"").freeze
17
20
  end
18
21
 
19
22
  def quote_column_name(name)
20
- self.class.quoted_column_names[name] ||= %Q("#{super.gsub('"', '""')}")
23
+ QUOTED_COLUMN_NAMES[name] ||= %Q("#{super.gsub('"', '""')}")
21
24
  end
22
25
 
23
26
  def quoted_time(value)
@@ -4,6 +4,12 @@ module ActiveRecord
4
4
  module ConnectionAdapters
5
5
  module SQLite3
6
6
  class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
7
+ def change_column(column_name, type, **options)
8
+ name = column_name.to_s
9
+ @columns_hash[name] = nil
10
+ column(name, type, **options)
11
+ end
12
+
7
13
  def references(*args, **options)
8
14
  super(*args, type: :integer, **options)
9
15
  end
@@ -84,11 +84,11 @@ module ActiveRecord
84
84
  table_sql = query_value(<<-SQL, "SCHEMA")
85
85
  SELECT sql
86
86
  FROM sqlite_master
87
- WHERE name = #{quote_table_name(table_name)} AND type = 'table'
87
+ WHERE name = #{quote(table_name)} AND type = 'table'
88
88
  UNION ALL
89
89
  SELECT sql
90
90
  FROM sqlite_temp_master
91
- WHERE name = #{quote_table_name(table_name)} AND type = 'table'
91
+ WHERE name = #{quote(table_name)} AND type = 'table'
92
92
  SQL
93
93
 
94
94
  table_sql.to_s.scan(/CONSTRAINT\s+(?<name>\w+)\s+CHECK\s+\((?<expression>(:?[^()]|\(\g<expression>\))+)\)/i).map do |name, expression|
@@ -287,10 +287,7 @@ module ActiveRecord
287
287
 
288
288
  def change_column(table_name, column_name, type, **options) # :nodoc:
289
289
  alter_table(table_name) do |definition|
290
- definition[column_name].instance_eval do
291
- self.type = aliased_types(type.to_s, type)
292
- self.options.merge!(options)
293
- end
290
+ definition.change_column(column_name, type, **options)
294
291
  end
295
292
  end
296
293
 
@@ -480,6 +477,7 @@ module ActiveRecord
480
477
  if column.has_default?
481
478
  type = lookup_cast_type_from_column(column)
482
479
  default = type.deserialize(column.default)
480
+ default = -> { column.default_function } if default.nil?
483
481
  end
484
482
 
485
483
  @definition.column(column_name, column.type,
@@ -9,8 +9,8 @@ module ActiveRecord
9
9
  module VERSION
10
10
  MAJOR = 7
11
11
  MINOR = 0
12
- TINY = 5
13
- PRE = nil
12
+ TINY = 8
13
+ PRE = "6"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -2,14 +2,14 @@
2
2
 
3
3
  module ActiveRecord
4
4
  module Locking
5
- # == What is Optimistic Locking
5
+ # == What is \Optimistic \Locking
6
6
  #
7
7
  # Optimistic locking allows multiple users to access the same record for edits, and assumes a minimum of
8
8
  # conflicts with the data. It does this by checking whether another process has made changes to a record since
9
- # it was opened, an <tt>ActiveRecord::StaleObjectError</tt> exception is thrown if that has occurred
9
+ # it was opened, an ActiveRecord::StaleObjectError exception is thrown if that has occurred
10
10
  # and the update is ignored.
11
11
  #
12
- # Check out <tt>ActiveRecord::Locking::Pessimistic</tt> for an alternative.
12
+ # Check out +ActiveRecord::Locking::Pessimistic+ for an alternative.
13
13
  #
14
14
  # == Usage
15
15
  #
@@ -69,6 +69,11 @@ module ActiveRecord
69
69
  end
70
70
  end
71
71
 
72
+ def initialize_dup(other) # :nodoc:
73
+ super
74
+ _clear_locking_column if locking_enabled?
75
+ end
76
+
72
77
  private
73
78
  def _create_record(attribute_names = self.attribute_names)
74
79
  if locking_enabled?
@@ -91,8 +96,7 @@ module ActiveRecord
91
96
  locking_column = self.class.locking_column
92
97
  lock_attribute_was = @attributes[locking_column]
93
98
 
94
- update_constraints = _primary_key_constraints_hash
95
- update_constraints[locking_column] = _lock_value_for_database(locking_column)
99
+ update_constraints = _query_constraints_hash
96
100
 
97
101
  attribute_names = attribute_names.dup if attribute_names.frozen?
98
102
  attribute_names << locking_column
@@ -118,16 +122,9 @@ module ActiveRecord
118
122
  end
119
123
 
120
124
  def destroy_row
121
- return super unless locking_enabled?
122
-
123
- locking_column = self.class.locking_column
125
+ affected_rows = super
124
126
 
125
- delete_constraints = _primary_key_constraints_hash
126
- delete_constraints[locking_column] = _lock_value_for_database(locking_column)
127
-
128
- affected_rows = self.class._delete_record(delete_constraints)
129
-
130
- if affected_rows != 1
127
+ if locking_enabled? && affected_rows != 1
131
128
  raise ActiveRecord::StaleObjectError.new(self, "destroy")
132
129
  end
133
130
 
@@ -142,6 +139,18 @@ module ActiveRecord
142
139
  end
143
140
  end
144
141
 
142
+ def _clear_locking_column
143
+ self[self.class.locking_column] = nil
144
+ clear_attribute_change(self.class.locking_column)
145
+ end
146
+
147
+ def _query_constraints_hash
148
+ return super unless locking_enabled?
149
+
150
+ locking_column = self.class.locking_column
151
+ super.merge(locking_column => _lock_value_for_database(locking_column))
152
+ end
153
+
145
154
  module ClassMethods
146
155
  DEFAULT_LOCKING_COLUMN = "lock_version"
147
156
 
@@ -159,10 +168,7 @@ module ActiveRecord
159
168
  end
160
169
 
161
170
  # The version column used for optimistic locking. Defaults to +lock_version+.
162
- def locking_column
163
- @locking_column = DEFAULT_LOCKING_COLUMN unless defined?(@locking_column)
164
- @locking_column
165
- end
171
+ attr_reader :locking_column
166
172
 
167
173
  # Reset the column used for optimistic locking back to the +lock_version+ default.
168
174
  def reset_locking_column
@@ -182,6 +188,14 @@ module ActiveRecord
182
188
  end
183
189
  super
184
190
  end
191
+
192
+ private
193
+ def inherited(base)
194
+ super
195
+ base.class_eval do
196
+ @locking_column = DEFAULT_LOCKING_COLUMN
197
+ end
198
+ end
185
199
  end
186
200
  end
187
201
 
@@ -56,12 +56,13 @@ module ActiveRecord
56
56
  super
57
57
  end
58
58
 
59
- def create_table(table_name, **options)
60
- if block_given?
61
- super { |t| yield compatible_table_definition(t) }
62
- else
63
- super
59
+ def change_column(table_name, column_name, type, **options)
60
+ if type == :datetime
61
+ options[:precision] ||= nil
64
62
  end
63
+
64
+ type = PostgreSQLCompat.compatible_timestamp_type(type, connection)
65
+ super
65
66
  end
66
67
 
67
68
  module TableDefinition
@@ -70,6 +71,11 @@ module ActiveRecord
70
71
  super
71
72
  end
72
73
 
74
+ def change(name, type, index: nil, **options)
75
+ options[:precision] ||= nil
76
+ super
77
+ end
78
+
73
79
  def column(name, type, index: nil, **options)
74
80
  options[:precision] ||= nil
75
81
  super
@@ -81,7 +87,7 @@ module ActiveRecord
81
87
  class << t
82
88
  prepend TableDefinition
83
89
  end
84
- t
90
+ super
85
91
  end
86
92
  end
87
93
 
@@ -105,30 +111,6 @@ module ActiveRecord
105
111
  end
106
112
  end
107
113
 
108
- def create_table(table_name, **options)
109
- if block_given?
110
- super { |t| yield compatible_table_definition(t) }
111
- else
112
- super
113
- end
114
- end
115
-
116
- def change_table(table_name, **options)
117
- if block_given?
118
- super { |t| yield compatible_table_definition(t) }
119
- else
120
- super
121
- end
122
- end
123
-
124
- def create_join_table(table_1, table_2, **options)
125
- if block_given?
126
- super { |t| yield compatible_table_definition(t) }
127
- else
128
- super
129
- end
130
- end
131
-
132
114
  def add_reference(table_name, ref_name, **options)
133
115
  if connection.adapter_name == "SQLite"
134
116
  options[:type] = :integer
@@ -182,30 +164,6 @@ module ActiveRecord
182
164
  end
183
165
  end
184
166
 
185
- def create_table(table_name, **options)
186
- if block_given?
187
- super { |t| yield compatible_table_definition(t) }
188
- else
189
- super
190
- end
191
- end
192
-
193
- def change_table(table_name, **options)
194
- if block_given?
195
- super { |t| yield compatible_table_definition(t) }
196
- else
197
- super
198
- end
199
- end
200
-
201
- def create_join_table(table_1, table_2, **options)
202
- if block_given?
203
- super { |t| yield compatible_table_definition(t) }
204
- else
205
- super
206
- end
207
- end
208
-
209
167
  def add_timestamps(table_name, **options)
210
168
  options[:precision] ||= nil
211
169
  super
@@ -551,6 +551,41 @@ module ActiveRecord
551
551
 
552
552
  # This must be defined before the inherited hook, below
553
553
  class Current < Migration # :nodoc:
554
+ def create_table(table_name, **options)
555
+ if block_given?
556
+ super { |t| yield compatible_table_definition(t) }
557
+ else
558
+ super
559
+ end
560
+ end
561
+
562
+ def change_table(table_name, **options)
563
+ if block_given?
564
+ super { |t| yield compatible_table_definition(t) }
565
+ else
566
+ super
567
+ end
568
+ end
569
+
570
+ def create_join_table(table_1, table_2, **options)
571
+ if block_given?
572
+ super { |t| yield compatible_table_definition(t) }
573
+ else
574
+ super
575
+ end
576
+ end
577
+
578
+ def drop_table(table_name, **options)
579
+ if block_given?
580
+ super { |t| yield compatible_table_definition(t) }
581
+ else
582
+ super
583
+ end
584
+ end
585
+
586
+ def compatible_table_definition(t)
587
+ t
588
+ end
554
589
  end
555
590
 
556
591
  def self.inherited(subclass) # :nodoc:
@@ -916,9 +951,7 @@ module ActiveRecord
916
951
  end
917
952
 
918
953
  def method_missing(method, *arguments, &block)
919
- arg_list = arguments.map(&:inspect) * ", "
920
-
921
- say_with_time "#{method}(#{arg_list})" do
954
+ say_with_time "#{method}(#{format_arguments(arguments)})" do
922
955
  unless connection.respond_to? :revert
923
956
  unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
924
957
  arguments[0] = proper_table_name(arguments.first, table_name_options)
@@ -1026,6 +1059,22 @@ module ActiveRecord
1026
1059
  end
1027
1060
  end
1028
1061
 
1062
+ def format_arguments(arguments)
1063
+ arg_list = arguments[0...-1].map(&:inspect)
1064
+ last_arg = arguments.last
1065
+ if last_arg.is_a?(Hash)
1066
+ last_arg = last_arg.reject { |k, _v| internal_option?(k) }
1067
+ arg_list << last_arg.inspect unless last_arg.empty?
1068
+ else
1069
+ arg_list << last_arg.inspect
1070
+ end
1071
+ arg_list.join(", ")
1072
+ end
1073
+
1074
+ def internal_option?(option_name)
1075
+ option_name.start_with?("_")
1076
+ end
1077
+
1029
1078
  def command_recorder
1030
1079
  CommandRecorder.new(connection)
1031
1080
  end
@@ -564,7 +564,7 @@ module ActiveRecord
564
564
  end
565
565
 
566
566
  # Returns true if this object was just created -- that is, prior to the last
567
- # save, the object didn't exist in the database and new_record? would have
567
+ # update or delete, the object didn't exist in the database and new_record? would have
568
568
  # returned true.
569
569
  def previously_new_record?
570
570
  @previously_new_record
@@ -663,6 +663,7 @@ module ActiveRecord
663
663
  def delete
664
664
  _delete_row if persisted?
665
665
  @destroyed = true
666
+ @previously_new_record = false
666
667
  freeze
667
668
  end
668
669
 
@@ -682,6 +683,7 @@ module ActiveRecord
682
683
  true
683
684
  end
684
685
  @destroyed = true
686
+ @previously_new_record = false
685
687
  freeze
686
688
  end
687
689
 
@@ -813,7 +815,7 @@ module ActiveRecord
813
815
  verify_readonly_attribute(name) || name
814
816
  end
815
817
 
816
- update_constraints = _primary_key_constraints_hash
818
+ update_constraints = _query_constraints_hash
817
819
  attributes = attributes.each_with_object({}) do |(k, v), h|
818
820
  h[k] = @attributes.write_cast_value(k, v)
819
821
  clear_attribute_change(k)
@@ -1028,7 +1030,7 @@ module ActiveRecord
1028
1030
  (self.class.default_scopes?(all_queries: true) || self.class.global_current_scope)
1029
1031
  end
1030
1032
 
1031
- def _primary_key_constraints_hash
1033
+ def _query_constraints_hash
1032
1034
  { @primary_key => id_in_database }
1033
1035
  end
1034
1036
 
@@ -1041,7 +1043,7 @@ module ActiveRecord
1041
1043
  end
1042
1044
 
1043
1045
  def _delete_row
1044
- self.class._delete_record(_primary_key_constraints_hash)
1046
+ self.class._delete_record(_query_constraints_hash)
1045
1047
  end
1046
1048
 
1047
1049
  def _touch_row(attribute_names, time)
@@ -1057,7 +1059,7 @@ module ActiveRecord
1057
1059
  def _update_row(attribute_names, attempted_action = "update")
1058
1060
  self.class._update_record(
1059
1061
  attributes_with_values(attribute_names),
1060
- _primary_key_constraints_hash
1062
+ _query_constraints_hash
1061
1063
  )
1062
1064
  end
1063
1065
 
@@ -28,7 +28,7 @@ module ActiveRecord
28
28
  end
29
29
 
30
30
  def cleanup_view_runtime
31
- if logger && logger.info? && ActiveRecord::Base.connected?
31
+ if logger && logger.info?
32
32
  db_rt_before_render = ActiveRecord::LogSubscriber.reset_runtime
33
33
  self.db_runtime = (db_runtime || 0) + db_rt_before_render
34
34
  runtime = super
@@ -42,9 +42,8 @@ module ActiveRecord
42
42
 
43
43
  def append_info_to_payload(payload)
44
44
  super
45
- if ActiveRecord::Base.connected?
46
- payload[:db_runtime] = (db_runtime || 0) + ActiveRecord::LogSubscriber.reset_runtime
47
- end
45
+
46
+ payload[:db_runtime] = (db_runtime || 0) + ActiveRecord::LogSubscriber.reset_runtime
48
47
  end
49
48
  end
50
49
  end
@@ -485,6 +485,10 @@ module ActiveRecord
485
485
  foreign_key
486
486
  end
487
487
 
488
+ def join_primary_type
489
+ type
490
+ end
491
+
488
492
  def join_foreign_key
489
493
  active_record_primary_key
490
494
  end
@@ -588,6 +592,10 @@ module ActiveRecord
588
592
  options[:polymorphic]
589
593
  end
590
594
 
595
+ def polymorphic_name
596
+ active_record.polymorphic_name
597
+ end
598
+
591
599
  def add_as_source(seed)
592
600
  seed
593
601
  end
@@ -18,7 +18,10 @@ module ActiveRecord
18
18
  def ids
19
19
  case value
20
20
  when Relation
21
- value.select_values.empty? ? value.select(primary_key) : value
21
+ relation = value
22
+ relation = relation.select(primary_key) if select_clause?
23
+ relation = relation.where(primary_type => polymorphic_name) if polymorphic_clause?
24
+ relation
22
25
  when Array
23
26
  value.map { |v| convert_to_id(v) }
24
27
  else
@@ -30,6 +33,22 @@ module ActiveRecord
30
33
  associated_table.join_primary_key
31
34
  end
32
35
 
36
+ def primary_type
37
+ associated_table.join_primary_type
38
+ end
39
+
40
+ def polymorphic_name
41
+ associated_table.polymorphic_name_association
42
+ end
43
+
44
+ def select_clause?
45
+ value.select_values.empty?
46
+ end
47
+
48
+ def polymorphic_clause?
49
+ primary_type && !value.where_values_hash.has_key?(primary_type)
50
+ end
51
+
33
52
  def convert_to_id(value)
34
53
  if value.respond_to?(primary_key)
35
54
  value.public_send(primary_key)
@@ -65,8 +65,7 @@ module ActiveRecord
65
65
  end
66
66
 
67
67
  def build_bind_attribute(column_name, value)
68
- type = table.type(column_name)
69
- Relation::QueryAttribute.new(column_name, type.immutable_value(value), type)
68
+ Relation::QueryAttribute.new(column_name, value, table.type(column_name))
70
69
  end
71
70
 
72
71
  def resolve_arel_attribute(table_name, column_name, &block)
@@ -5,6 +5,20 @@ require "active_model/attribute"
5
5
  module ActiveRecord
6
6
  class Relation
7
7
  class QueryAttribute < ActiveModel::Attribute # :nodoc:
8
+ def initialize(...)
9
+ super
10
+
11
+ # The query attribute value may be mutated before we actually "compile" the query.
12
+ # To avoid that if the type uses a serializer we eagerly compute the value for database
13
+ if value_before_type_cast.is_a?(StatementCache::Substitute)
14
+ # we don't need to serialize StatementCache::Substitute
15
+ elsif @type.serialized?
16
+ value_for_database
17
+ elsif @type.mutable? # If the type is simply mutable, we deep_dup it.
18
+ @value_before_type_cast = @value_before_type_cast.deep_dup
19
+ end
20
+ end
21
+
8
22
  def type_cast(value)
9
23
  value
10
24
  end
@@ -35,6 +49,15 @@ module ActiveRecord
35
49
  @_unboundable
36
50
  end
37
51
 
52
+ def ==(other)
53
+ super && value_for_database == other.value_for_database
54
+ end
55
+ alias eql? ==
56
+
57
+ def hash
58
+ [self.class, name, value_for_database, type].hash
59
+ end
60
+
38
61
  private
39
62
  def infinity?(value)
40
63
  value.respond_to?(:infinite?) && value.infinite?
@@ -77,7 +77,11 @@ module ActiveRecord
77
77
  associations.each do |association|
78
78
  reflection = scope_association_reflection(association)
79
79
  @scope.joins!(association)
80
- self.not(association => { reflection.association_primary_key => nil })
80
+ if reflection.options[:class_name]
81
+ self.not(association => { reflection.association_primary_key => nil })
82
+ else
83
+ self.not(reflection.table_name => { reflection.association_primary_key => nil })
84
+ end
81
85
  end
82
86
 
83
87
  @scope
@@ -105,7 +109,11 @@ module ActiveRecord
105
109
  associations.each do |association|
106
110
  reflection = scope_association_reflection(association)
107
111
  @scope.left_outer_joins!(association)
108
- @scope.where!(association => { reflection.association_primary_key => nil })
112
+ if reflection.options[:class_name]
113
+ @scope.where!(association => { reflection.association_primary_key => nil })
114
+ else
115
+ @scope.where!(reflection.table_name => { reflection.association_primary_key => nil })
116
+ end
109
117
  end
110
118
 
111
119
  @scope
@@ -436,13 +444,16 @@ module ActiveRecord
436
444
  self
437
445
  end
438
446
 
439
- # Allows to specify an order by a specific set of values. Depending on your
440
- # adapter this will either use a CASE statement or a built-in function.
447
+ # Allows to specify an order by a specific set of values.
441
448
  #
442
449
  # User.in_order_of(:id, [1, 5, 3])
443
450
  # # SELECT "users".* FROM "users"
444
- # # ORDER BY FIELD("users"."id", 1, 5, 3)
445
451
  # # WHERE "users"."id" IN (1, 5, 3)
452
+ # # ORDER BY CASE
453
+ # # WHEN "users"."id" = 1 THEN 1
454
+ # # WHEN "users"."id" = 5 THEN 2
455
+ # # WHEN "users"."id" = 3 THEN 3
456
+ # # END ASC
446
457
  #
447
458
  def in_order_of(column, values)
448
459
  klass.disallow_raw_sql!([column], permit: connection.column_name_with_order_matcher)
@@ -454,9 +465,16 @@ module ActiveRecord
454
465
  values = values.map { |value| type_caster.type_cast_for_database(column, value) }
455
466
  arel_column = column.is_a?(Symbol) ? order_column(column.to_s) : column
456
467
 
468
+ where_clause =
469
+ if values.include?(nil)
470
+ arel_column.in(values.compact).or(arel_column.eq(nil))
471
+ else
472
+ arel_column.in(values)
473
+ end
474
+
457
475
  spawn
458
- .order!(connection.field_ordered_value(arel_column, values))
459
- .where!(arel_column.in(values))
476
+ .order!(build_case_for_value_position(arel_column, values))
477
+ .where!(where_clause)
460
478
  end
461
479
 
462
480
  # Replaces any existing order defined on the relation with the specified order.
@@ -1661,6 +1679,15 @@ module ActiveRecord
1661
1679
  end
1662
1680
  end
1663
1681
 
1682
+ def build_case_for_value_position(column, values)
1683
+ node = Arel::Nodes::Case.new
1684
+ values.each.with_index(1) do |value, order|
1685
+ node.when(column.eq(value)).then(order)
1686
+ end
1687
+
1688
+ Arel::Nodes::Ascending.new(node)
1689
+ end
1690
+
1664
1691
  def resolve_arel_attributes(attrs)
1665
1692
  attrs.flat_map do |attr|
1666
1693
  case attr
@@ -108,7 +108,7 @@ module ActiveRecord
108
108
  type = if type_overrides.is_a?(Array)
109
109
  type_overrides.first
110
110
  else
111
- column_type(columns.first, type_overrides)
111
+ column_type(columns.first, 0, type_overrides)
112
112
  end
113
113
 
114
114
  rows.map do |(value)|
@@ -118,7 +118,7 @@ module ActiveRecord
118
118
  types = if type_overrides.is_a?(Array)
119
119
  type_overrides
120
120
  else
121
- columns.map { |name| column_type(name, type_overrides) }
121
+ columns.map.with_index { |name, i| column_type(name, i, type_overrides) }
122
122
  end
123
123
 
124
124
  rows.map do |values|
@@ -135,9 +135,11 @@ module ActiveRecord
135
135
  end
136
136
 
137
137
  private
138
- def column_type(name, type_overrides = {})
138
+ def column_type(name, index, type_overrides)
139
139
  type_overrides.fetch(name) do
140
- column_types.fetch(name, Type.default_value)
140
+ column_types.fetch(index) do
141
+ column_types.fetch(name, Type.default_value)
142
+ end
141
143
  end
142
144
  end
143
145
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module ActiveRecord
4
4
  class TableMetadata # :nodoc:
5
- delegate :join_primary_key, :join_foreign_key, :join_foreign_type, to: :reflection
5
+ delegate :join_primary_key, :join_primary_type, :join_foreign_key, :join_foreign_type, to: :reflection
6
6
 
7
7
  def initialize(klass, arel_table, reflection = nil)
8
8
  @klass = klass
@@ -19,7 +19,7 @@ module ActiveRecord
19
19
  end
20
20
 
21
21
  def has_column?(column_name)
22
- klass&.columns_hash.key?(column_name)
22
+ klass&.columns_hash&.key?(column_name)
23
23
  end
24
24
 
25
25
  def associated_with?(table_name)
@@ -54,6 +54,10 @@ module ActiveRecord
54
54
  reflection&.polymorphic?
55
55
  end
56
56
 
57
+ def polymorphic_name_association
58
+ reflection&.polymorphic_name
59
+ end
60
+
57
61
  def through_association?
58
62
  reflection&.through_reflection?
59
63
  end
@@ -336,9 +336,9 @@ module ActiveRecord
336
336
  @_trigger_update_callback = @_trigger_destroy_callback = false if force_restore_state
337
337
  end
338
338
 
339
- # Executes +method+ within a transaction and captures its return value as a
340
- # status flag. If the status is true the transaction is committed, otherwise
341
- # a ROLLBACK is issued. In any case the status flag is returned.
339
+ # Executes a block within a transaction and captures its return value as a
340
+ # status flag. If the status is true, the transaction is committed,
341
+ # otherwise a ROLLBACK is issued. In any case, the status flag is returned.
342
342
  #
343
343
  # This method is available within the context of an ActiveRecord::Base
344
344
  # instance.
@@ -55,6 +55,10 @@ module ActiveRecord
55
55
  coder.respond_to?(:object_class) && value.is_a?(coder.object_class)
56
56
  end
57
57
 
58
+ def serialized? # :nodoc:
59
+ true
60
+ end
61
+
58
62
  private
59
63
  def default_value?(value)
60
64
  value == coder.load(nil)
@@ -18,6 +18,10 @@ module Arel # :nodoc: all
18
18
  children[1]
19
19
  end
20
20
 
21
+ def fetch_attribute(&block)
22
+ children.any? && children.all? { |child| child.fetch_attribute(&block) }
23
+ end
24
+
21
25
  def hash
22
26
  children.hash
23
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.5
4
+ version: 7.0.8.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-24 00:00:00.000000000 Z
11
+ date: 2024-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 7.0.5
19
+ version: 7.0.8.6
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.0.5
26
+ version: 7.0.8.6
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activemodel
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 7.0.5
33
+ version: 7.0.8.6
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.0.5
40
+ version: 7.0.8.6
41
41
  description: Databases on Rails. Build a persistent domain model by mapping database
42
42
  tables to Ruby classes. Strong conventions for associations, validations, aggregations,
43
43
  migrations, and testing come baked-in.
@@ -434,10 +434,10 @@ licenses:
434
434
  - MIT
435
435
  metadata:
436
436
  bug_tracker_uri: https://github.com/rails/rails/issues
437
- changelog_uri: https://github.com/rails/rails/blob/v7.0.5/activerecord/CHANGELOG.md
438
- documentation_uri: https://api.rubyonrails.org/v7.0.5/
437
+ changelog_uri: https://github.com/rails/rails/blob/v7.0.8.6/activerecord/CHANGELOG.md
438
+ documentation_uri: https://api.rubyonrails.org/v7.0.8.6/
439
439
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
440
- source_code_uri: https://github.com/rails/rails/tree/v7.0.5/activerecord
440
+ source_code_uri: https://github.com/rails/rails/tree/v7.0.8.6/activerecord
441
441
  rubygems_mfa_required: 'true'
442
442
  post_install_message:
443
443
  rdoc_options:
@@ -456,7 +456,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
456
456
  - !ruby/object:Gem::Version
457
457
  version: '0'
458
458
  requirements: []
459
- rubygems_version: 3.4.10
459
+ rubygems_version: 3.5.16
460
460
  signing_key:
461
461
  specification_version: 4
462
462
  summary: Object-relational mapper framework (part of Rails).