activerecord 8.0.0.1 → 8.0.2

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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +208 -0
  3. data/lib/active_record/associations/alias_tracker.rb +6 -4
  4. data/lib/active_record/associations/belongs_to_association.rb +7 -1
  5. data/lib/active_record/associations/join_dependency/join_association.rb +25 -27
  6. data/lib/active_record/attribute_methods/primary_key.rb +2 -1
  7. data/lib/active_record/attribute_methods.rb +22 -17
  8. data/lib/active_record/attributes.rb +2 -2
  9. data/lib/active_record/autosave_association.rb +21 -11
  10. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +17 -14
  11. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +47 -34
  12. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +5 -1
  13. data/lib/active_record/connection_adapters/abstract_adapter.rb +39 -22
  14. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +14 -7
  15. data/lib/active_record/connection_adapters/mysql/quoting.rb +7 -1
  16. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +7 -0
  17. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +57 -11
  18. data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -1
  19. data/lib/active_record/connection_adapters/pool_config.rb +7 -7
  20. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +14 -12
  21. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +1 -1
  22. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +1 -1
  23. data/lib/active_record/connection_adapters/postgresql_adapter.rb +7 -2
  24. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +5 -1
  25. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +13 -0
  26. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +2 -0
  27. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +7 -2
  28. data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
  29. data/lib/active_record/connection_adapters/trilogy_adapter.rb +1 -1
  30. data/lib/active_record/core.rb +31 -2
  31. data/lib/active_record/counter_cache.rb +1 -1
  32. data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -1
  33. data/lib/active_record/delegated_type.rb +17 -17
  34. data/lib/active_record/future_result.rb +3 -3
  35. data/lib/active_record/gem_version.rb +2 -2
  36. data/lib/active_record/migration/command_recorder.rb +5 -2
  37. data/lib/active_record/railties/databases.rake +1 -1
  38. data/lib/active_record/relation/calculations.rb +23 -17
  39. data/lib/active_record/relation/predicate_builder/association_query_value.rb +2 -0
  40. data/lib/active_record/relation/query_attribute.rb +1 -1
  41. data/lib/active_record/relation/query_methods.rb +1 -1
  42. data/lib/active_record/relation.rb +1 -1
  43. data/lib/active_record/schema_dumper.rb +29 -11
  44. data/lib/active_record/signed_id.rb +4 -3
  45. data/lib/active_record/statement_cache.rb +2 -2
  46. data/lib/active_record/transactions.rb +5 -6
  47. data/lib/active_record.rb +4 -2
  48. data/lib/arel/collectors/bind.rb +1 -1
  49. data/lib/arel/collectors/sql_string.rb +1 -1
  50. data/lib/arel/collectors/substitute_binds.rb +2 -2
  51. data/lib/arel/nodes/binary.rb +1 -1
  52. data/lib/arel/nodes/node.rb +1 -1
  53. data/lib/arel/nodes/sql_literal.rb +1 -1
  54. data/lib/arel/visitors/to_sql.rb +1 -1
  55. metadata +10 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '08d99704536322248d3c491dc890d68ae27698b4bb368e46a5e9ef40689bf988'
4
- data.tar.gz: 910326d6346f200b00a670487236ad1e67862ba0746c869ea12ea283994ec74a
3
+ metadata.gz: 82c8ca907ebe4ec74622fb27ce477cdd5a4536e05bb25334c3551560324507cd
4
+ data.tar.gz: 88787eb24c8acb59dc3517d85e919a50d85bf3c0bff149f59f76d2bf6b8495d8
5
5
  SHA512:
6
- metadata.gz: 32398ee71740d80113c849cf81bf8f8a60531df263042eeb87c38197d28b5f25b5c3805cc70aef9c4228c6b1d3571312ed0b7a1bee7713f02e0c40dec37d39e1
7
- data.tar.gz: 0e6664b8b897e0997bfedc56d5cc3cc2524fb7df4fd4d2f3ee394079cdc08e1648155a75f215d38177e51eddc98a6ca817390a6149ee19eb64a65024f9b30602
6
+ metadata.gz: ea3714004780235f5bb1c78e8b667d229e642942b3ea12163b923d72fa66668e1bd9fc848c87347d96a83c85d3934e499411118883fd2a9c38779a87f031d83c
7
+ data.tar.gz: 7bacd8bf3eb5712fecdcbba881a2a92f9f4f6fe609c644802b12e423a3f95e7b5953669715ad4215b7170a80f37c70686d2bf090872ef585fb0f4ed8001ff03e
data/CHANGELOG.md CHANGED
@@ -1,3 +1,210 @@
1
+ ## Rails 8.0.2 (March 12, 2025) ##
2
+
3
+ * No changes.
4
+
5
+
6
+ ## Rails 8.0.2 (March 12, 2025) ##
7
+
8
+ * Fix inverting `rename_enum_value` when `:from`/`:to` are provided.
9
+
10
+ *fatkodima*
11
+
12
+ * Prevent persisting invalid record.
13
+
14
+ *Edouard Chin*
15
+
16
+ * Fix inverting `drop_table` without options.
17
+
18
+ *fatkodima*
19
+
20
+ * Fix count with group by qualified name on loaded relation.
21
+
22
+ *Ryuta Kamizono*
23
+
24
+ * Fix `sum` with qualified name on loaded relation.
25
+
26
+ *Chris Gunther*
27
+
28
+ * The SQLite3 adapter quotes non-finite Numeric values like "Infinity" and "NaN".
29
+
30
+ *Mike Dalessio*
31
+
32
+ * Handle libpq returning a database version of 0 on no/bad connection in `PostgreSQLAdapter`.
33
+
34
+ Before, this version would be cached and an error would be raised during connection configuration when
35
+ comparing it with the minimum required version for the adapter. This meant that the connection could
36
+ never be successfully configured on subsequent reconnection attempts.
37
+
38
+ Now, this is treated as a connection failure consistent with libpq, raising a `ActiveRecord::ConnectionFailed`
39
+ and ensuring the version isn't cached, which allows the version to be retrieved on the next connection attempt.
40
+
41
+ *Joshua Young*, *Rian McGuire*
42
+
43
+ * Fix error handling during connection configuration.
44
+
45
+ Active Record wasn't properly handling errors during the connection configuration phase.
46
+ This could lead to a partially configured connection being used, resulting in various exceptions,
47
+ the most common being with the PostgreSQLAdapter raising `undefined method `key?' for nil`
48
+ or `TypeError: wrong argument type nil (expected PG::TypeMap)`.
49
+
50
+ *Jean Boussier*
51
+
52
+ * Fix a case where a non-retryable query could be marked retryable.
53
+
54
+ *Hartley McGuire*
55
+
56
+ * Handle circular references when autosaving associations.
57
+
58
+ *zzak*
59
+
60
+ * PoolConfig no longer keeps a reference to the connection class.
61
+
62
+ Keeping a reference to the class caused subtle issues when combined with reloading in
63
+ development. Fixes #54343.
64
+
65
+ *Mike Dalessio*
66
+
67
+ * Fix SQL notifications sometimes not sent when using async queries.
68
+
69
+ ```ruby
70
+ Post.async_count
71
+ ActiveSupport::Notifications.subscribed(->(*) { "Will never reach here" }) do
72
+ Post.count
73
+ end
74
+ ```
75
+
76
+ In rare circumstances and under the right race condition, Active Support notifications
77
+ would no longer be dispatched after using an asynchronous query.
78
+ This is now fixed.
79
+
80
+ *Edouard Chin*
81
+
82
+ * Fix support for PostgreSQL enum types with commas in their name.
83
+
84
+ *Arthur Hess*
85
+
86
+ * Fix inserts on MySQL with no RETURNING support for a table with multiple auto populated columns.
87
+
88
+ *Nikita Vasilevsky*
89
+
90
+ * Fix joining on a scoped association with string joins and bind parameters.
91
+
92
+ ```ruby
93
+ class Instructor < ActiveRecord::Base
94
+ has_many :instructor_roles, -> { active }
95
+ end
96
+
97
+ class InstructorRole < ActiveRecord::Base
98
+ scope :active, -> {
99
+ joins("JOIN students ON instructor_roles.student_id = students.id")
100
+ .where(students { status: 1 })
101
+ }
102
+ end
103
+
104
+ Instructor.joins(:instructor_roles).first
105
+ ```
106
+
107
+ The above example would result in `ActiveRecord::StatementInvalid` because the
108
+ `active` scope bind parameters would be lost.
109
+
110
+ *Jean Boussier*
111
+
112
+ * Fix a potential race condition with system tests and transactional fixtures.
113
+
114
+ *Sjoerd Lagarde*
115
+
116
+ * Fix autosave associations to no longer validated unmodified associated records.
117
+
118
+ Active Record was incorrectly performing validation on associated record that
119
+ weren't created nor modified as part of the transaction:
120
+
121
+ ```ruby
122
+ Post.create!(author: User.find(1)) # Fail if user is invalid
123
+ ```
124
+
125
+ *Jean Boussier*
126
+
127
+ * Remember when a database connection has recently been verified (for
128
+ two seconds, by default), to avoid repeated reverifications during a
129
+ single request.
130
+
131
+ This should recreate a similar rate of verification as in Rails 7.1,
132
+ where connections are leased for the duration of a request, and thus
133
+ only verified once.
134
+
135
+ *Matthew Draper*
136
+
137
+
138
+ ## Rails 8.0.1 (December 13, 2024) ##
139
+
140
+ * Fix removing foreign keys with :restrict action for MySQL.
141
+
142
+ *fatkodima*
143
+
144
+ * Fix a race condition in `ActiveRecord::Base#method_missing` when lazily defining attributes.
145
+
146
+ If multiple thread were concurrently triggering attribute definition on the same model,
147
+ it could result in a `NoMethodError` being raised.
148
+
149
+ *Jean Boussier*
150
+
151
+ * Fix MySQL default functions getting dropped when changing a column's nullability.
152
+
153
+ *Bastian Bartmann*
154
+
155
+ * Fix `add_unique_constraint`/`add_check_constraint`/`add_foreign_key` to be revertible when given invalid options.
156
+
157
+ *fatkodima*
158
+
159
+ * Fix asynchronous destroying of polymorphic `belongs_to` associations.
160
+
161
+ *fatkodima*
162
+
163
+ * Fix `insert_all` to not update existing records.
164
+
165
+ *fatkodima*
166
+
167
+ * `NOT VALID` constraints should not dump in `create_table`.
168
+
169
+ *Ryuta Kamizono*
170
+
171
+ * Fix finding by nil composite primary key association.
172
+
173
+ *fatkodima*
174
+
175
+ * Properly reset composite primary key configuration when setting a primary key.
176
+
177
+ *fatkodima*
178
+
179
+ * Fix Mysql2Adapter support for prepared statements
180
+
181
+ Using prepared statements with MySQL could result in a `NoMethodError` exception.
182
+
183
+ *Jean Boussier*, *Leo Arnold*, *zzak*
184
+
185
+ * Fix parsing of SQLite foreign key names when they contain non-ASCII characters
186
+
187
+ *Zacharias Knudsen*
188
+
189
+ * Fix parsing of MySQL 8.0.16+ CHECK constraints when they contain new lines.
190
+
191
+ *Steve Hill*
192
+
193
+ * Ensure normalized attribute queries use `IS NULL` consistently for `nil` and normalized `nil` values.
194
+
195
+ *Joshua Young*
196
+
197
+ * Fix `sum` when performing a grouped calculation.
198
+
199
+ `User.group(:friendly).sum` no longer worked. This is fixed.
200
+
201
+ *Edouard Chin*
202
+
203
+ * Restore back the ability to pass only database name to `DATABASE_URL`.
204
+
205
+ *fatkodima*
206
+
207
+
1
208
  ## Rails 8.0.0.1 (December 10, 2024) ##
2
209
 
3
210
  * No changes.
@@ -11,6 +218,7 @@
11
218
 
12
219
  *zzak*
13
220
 
221
+
14
222
  ## Rails 8.0.0.rc2 (October 30, 2024) ##
15
223
 
16
224
  * NULLS NOT DISTINCT works with UNIQUE CONSTRAINT as well as UNIQUE INDEX.
@@ -26,16 +26,18 @@ module ActiveRecord
26
26
  end
27
27
 
28
28
  def self.initial_count_for(connection, name, table_joins)
29
- quoted_name = nil
29
+ quoted_name_escaped = nil
30
+ name_escaped = nil
30
31
 
31
32
  counts = table_joins.map do |join|
32
33
  if join.is_a?(Arel::Nodes::StringJoin)
33
- # quoted_name should be case ignored as some database adapters (Oracle) return quoted name in uppercase
34
- quoted_name ||= connection.quote_table_name(name)
34
+ # quoted_name_escaped should be case ignored as some database adapters (Oracle) return quoted name in uppercase
35
+ quoted_name_escaped ||= Regexp.escape(connection.quote_table_name(name))
36
+ name_escaped ||= Regexp.escape(name)
35
37
 
36
38
  # Table names + table aliases
37
39
  join.left.scan(
38
- /JOIN(?:\s+\w+)?\s+(?:\S+\s+)?(?:#{quoted_name}|#{name})\sON/i
40
+ /JOIN(?:\s+\w+)?\s+(?:\S+\s+)?(?:#{quoted_name_escaped}|#{name_escaped})\sON/i
39
41
  ).size
40
42
  elsif join.is_a?(Arel::Nodes::Join)
41
43
  join.left.name == name ? 1 : 0
@@ -19,10 +19,16 @@ module ActiveRecord
19
19
  id = owner.public_send(reflection.foreign_key)
20
20
  end
21
21
 
22
+ association_class = if reflection.polymorphic?
23
+ owner.public_send(reflection.foreign_type)
24
+ else
25
+ reflection.klass
26
+ end
27
+
22
28
  enqueue_destroy_association(
23
29
  owner_model_name: owner.class.to_s,
24
30
  owner_id: owner.id,
25
- association_class: reflection.klass.to_s,
31
+ association_class: association_class.to_s,
26
32
  association_ids: [id],
27
33
  association_primary_key_column: primary_key_column,
28
34
  ensuring_owner_was_method: options.fetch(:ensuring_owner_was, nil)
@@ -38,41 +38,39 @@ module ActiveRecord
38
38
  chain << [reflection, table]
39
39
  end
40
40
 
41
- base_klass.with_connection do |connection|
42
- # The chain starts with the target table, but we want to end with it here (makes
43
- # more sense in this context), so we reverse
44
- chain.reverse_each do |reflection, table|
45
- klass = reflection.klass
41
+ # The chain starts with the target table, but we want to end with it here (makes
42
+ # more sense in this context), so we reverse
43
+ chain.reverse_each do |reflection, table|
44
+ klass = reflection.klass
46
45
 
47
- scope = reflection.join_scope(table, foreign_table, foreign_klass)
46
+ scope = reflection.join_scope(table, foreign_table, foreign_klass)
48
47
 
49
- unless scope.references_values.empty?
50
- associations = scope.eager_load_values | scope.includes_values
48
+ unless scope.references_values.empty?
49
+ associations = scope.eager_load_values | scope.includes_values
51
50
 
52
- unless associations.empty?
53
- scope.joins! scope.construct_join_dependency(associations, Arel::Nodes::OuterJoin)
54
- end
51
+ unless associations.empty?
52
+ scope.joins! scope.construct_join_dependency(associations, Arel::Nodes::OuterJoin)
55
53
  end
54
+ end
56
55
 
57
- arel = scope.arel(alias_tracker.aliases)
58
- nodes = arel.constraints.first
56
+ arel = scope.arel(alias_tracker.aliases)
57
+ nodes = arel.constraints.first
59
58
 
60
- if nodes.is_a?(Arel::Nodes::And)
61
- others = nodes.children.extract! do |node|
62
- !Arel.fetch_attribute(node) { |attr| attr.relation.name == table.name }
63
- end
59
+ if nodes.is_a?(Arel::Nodes::And)
60
+ others = nodes.children.extract! do |node|
61
+ !Arel.fetch_attribute(node) { |attr| attr.relation.name == table.name }
64
62
  end
63
+ end
65
64
 
66
- joins << join_type.new(table, Arel::Nodes::On.new(nodes))
65
+ joins << join_type.new(table, Arel::Nodes::On.new(nodes))
67
66
 
68
- if others && !others.empty?
69
- joins.concat arel.join_sources
70
- append_constraints(connection, joins.last, others)
71
- end
72
-
73
- # The current table in this iteration becomes the foreign table in the next
74
- foreign_table, foreign_klass = table, klass
67
+ if others && !others.empty?
68
+ joins.concat arel.join_sources
69
+ append_constraints(joins.last, others)
75
70
  end
71
+
72
+ # The current table in this iteration becomes the foreign table in the next
73
+ foreign_table, foreign_klass = table, klass
76
74
  end
77
75
 
78
76
  joins
@@ -91,10 +89,10 @@ module ActiveRecord
91
89
  end
92
90
 
93
91
  private
94
- def append_constraints(connection, join, constraints)
92
+ def append_constraints(join, constraints)
95
93
  if join.is_a?(Arel::Nodes::StringJoin)
96
94
  join_string = Arel::Nodes::And.new(constraints.unshift join.left)
97
- join.left = Arel.sql(connection.visitor.compile(join_string))
95
+ join.left = join_string
98
96
  else
99
97
  right = join.right
100
98
  right.expr = Arel::Nodes::And.new(constraints.unshift right.expr)
@@ -129,12 +129,13 @@ module ActiveRecord
129
129
  # Project.primary_key # => "foo_id"
130
130
  def primary_key=(value)
131
131
  @primary_key = if value.is_a?(Array)
132
- @composite_primary_key = true
133
132
  include CompositePrimaryKey
134
133
  @primary_key = value.map { |v| -v.to_s }.freeze
135
134
  elsif value
136
135
  -value.to_s
137
136
  end
137
+
138
+ @composite_primary_key = value.is_a?(Array)
138
139
  @attributes_builder = nil
139
140
  end
140
141
 
@@ -116,10 +116,11 @@ module ActiveRecord
116
116
  alias_attribute :id_value, :id if _has_attribute?("id")
117
117
  end
118
118
 
119
- @attribute_methods_generated = true
120
-
121
119
  generate_alias_attributes
120
+
121
+ @attribute_methods_generated = true
122
122
  end
123
+
123
124
  true
124
125
  end
125
126
 
@@ -472,23 +473,27 @@ module ActiveRecord
472
473
  end
473
474
 
474
475
  def method_missing(name, ...)
475
- unless self.class.attribute_methods_generated?
476
- if self.class.method_defined?(name)
477
- # The method is explicitly defined in the model, but calls a generated
478
- # method with super. So we must resume the call chain at the right step.
479
- last_method = method(name)
480
- last_method = last_method.super_method while last_method.super_method
481
- self.class.define_attribute_methods
482
- if last_method.super_method
483
- return last_method.super_method.call(...)
484
- end
485
- elsif self.class.define_attribute_methods
486
- # Some attribute methods weren't generated yet, we retry the call
487
- return public_send(name, ...)
488
- end
476
+ # We can't know whether some method was defined or not because
477
+ # multiple thread might be concurrently be in this code path.
478
+ # So the first one would define the methods and the others would
479
+ # appear to already have them.
480
+ self.class.define_attribute_methods
481
+
482
+ # So in all cases we must behave as if the method was just defined.
483
+ method = begin
484
+ self.class.public_instance_method(name)
485
+ rescue NameError
486
+ nil
489
487
  end
490
488
 
491
- super
489
+ # The method might be explicitly defined in the model, but call a generated
490
+ # method with super. So we must resume the call chain at the right step.
491
+ method = method.super_method while method && !method.owner.is_a?(GeneratedAttributeMethods)
492
+ if method
493
+ method.bind_call(self, ...)
494
+ else
495
+ super
496
+ end
492
497
  end
493
498
 
494
499
  def attribute_method?(attr_name)
@@ -178,8 +178,8 @@ module ActiveRecord
178
178
  # @currency_converter = currency_converter
179
179
  # end
180
180
  #
181
- # # value will be the result of +deserialize+ or
182
- # # +cast+. Assumed to be an instance of +Money+ in
181
+ # # value will be the result of #deserialize or
182
+ # # #cast. Assumed to be an instance of Money in
183
183
  # # this case.
184
184
  # def serialize(value)
185
185
  # value_in_bitcoins = @currency_converter.convert_to_bitcoins(value)
@@ -372,19 +372,29 @@ module ActiveRecord
372
372
  return true if record.destroyed? || (association.options[:autosave] && record.marked_for_destruction?)
373
373
 
374
374
  context = validation_context if custom_validation_context?
375
+ return true if record.valid?(context)
375
376
 
376
- unless valid = record.valid?(context)
377
- if association.options[:autosave]
378
- record.errors.each { |error|
379
- self.errors.objects.append(
380
- Associations::NestedError.new(association, error)
381
- )
382
- }
383
- else
384
- errors.add(association.reflection.name)
385
- end
377
+ if record.changed? || record.new_record? || context
378
+ associated_errors = record.errors.objects
379
+ else
380
+ # If there are existing invalid records in the DB, we should still be able to reference them.
381
+ # Unless a record (no matter where in the association chain) is invalid and is being changed.
382
+ associated_errors = record.errors.objects.select { |error| error.is_a?(Associations::NestedError) }
386
383
  end
387
- valid
384
+
385
+ if association.options[:autosave]
386
+ return if equal?(record)
387
+
388
+ associated_errors.each { |error|
389
+ errors.objects.append(
390
+ Associations::NestedError.new(association, error)
391
+ )
392
+ }
393
+ elsif associated_errors.any?
394
+ errors.add(association.reflection.name)
395
+ end
396
+
397
+ errors.any?
388
398
  end
389
399
 
390
400
  # Is used as an around_save callback to check while saving a collection
@@ -54,19 +54,22 @@ module ActiveRecord
54
54
  # about the model. The model needs to pass a connection specification name to the handler,
55
55
  # in order to look up the correct connection pool.
56
56
  class ConnectionHandler
57
- class StringConnectionName # :nodoc:
58
- attr_reader :name
59
-
60
- def initialize(name)
57
+ class ConnectionDescriptor # :nodoc:
58
+ def initialize(name, primary = false)
61
59
  @name = name
60
+ @primary = primary
61
+ end
62
+
63
+ def name
64
+ primary_class? ? "ActiveRecord::Base" : @name
62
65
  end
63
66
 
64
67
  def primary_class?
65
- false
68
+ @primary
66
69
  end
67
70
 
68
71
  def current_preventing_writes
69
- false
72
+ ActiveRecord::Base.preventing_writes?(@name)
70
73
  end
71
74
  end
72
75
 
@@ -115,7 +118,7 @@ module ActiveRecord
115
118
  pool_config = resolve_pool_config(config, owner_name, role, shard)
116
119
  db_config = pool_config.db_config
117
120
 
118
- pool_manager = set_pool_manager(pool_config.connection_name)
121
+ pool_manager = set_pool_manager(pool_config.connection_descriptor)
119
122
 
120
123
  # If there is an existing pool with the same values as the pool_config
121
124
  # don't remove the connection. Connections should only be removed if we are
@@ -127,8 +130,8 @@ module ActiveRecord
127
130
  # Update the pool_config's connection class if it differs. This is used
128
131
  # for ensuring that ActiveRecord::Base and the primary_abstract_class use
129
132
  # the same pool. Without this granular swapping will not work correctly.
130
- if owner_name.primary_class? && (existing_pool_config.connection_class != owner_name)
131
- existing_pool_config.connection_class = owner_name
133
+ if owner_name.primary_class? && (existing_pool_config.connection_descriptor != owner_name)
134
+ existing_pool_config.connection_descriptor = owner_name
132
135
  end
133
136
 
134
137
  existing_pool_config.pool
@@ -137,7 +140,7 @@ module ActiveRecord
137
140
  pool_manager.set_pool_config(role, shard, pool_config)
138
141
 
139
142
  payload = {
140
- connection_name: pool_config.connection_name,
143
+ connection_name: pool_config.connection_descriptor.name,
141
144
  role: role,
142
145
  shard: shard,
143
146
  config: db_config.configuration_hash
@@ -242,8 +245,8 @@ module ActiveRecord
242
245
  end
243
246
 
244
247
  # Get the existing pool manager or initialize and assign a new one.
245
- def set_pool_manager(connection_name)
246
- connection_name_to_pool_manager[connection_name] ||= PoolManager.new
248
+ def set_pool_manager(connection_descriptor)
249
+ connection_name_to_pool_manager[connection_descriptor.name] ||= PoolManager.new
247
250
  end
248
251
 
249
252
  def pool_managers
@@ -278,9 +281,9 @@ module ActiveRecord
278
281
 
279
282
  def determine_owner_name(owner_name, config)
280
283
  if owner_name.is_a?(String) || owner_name.is_a?(Symbol)
281
- StringConnectionName.new(owner_name.to_s)
284
+ ConnectionDescriptor.new(owner_name.to_s)
282
285
  elsif config.is_a?(Symbol)
283
- StringConnectionName.new(config.to_s)
286
+ ConnectionDescriptor.new(config.to_s)
284
287
  else
285
288
  owner_name
286
289
  end