activerecord 7.1.3.1 → 7.1.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +266 -0
  3. data/lib/active_record/associations/belongs_to_association.rb +4 -4
  4. data/lib/active_record/associations/collection_association.rb +4 -4
  5. data/lib/active_record/associations/has_many_association.rb +2 -2
  6. data/lib/active_record/associations/has_one_association.rb +2 -2
  7. data/lib/active_record/associations/join_dependency.rb +6 -8
  8. data/lib/active_record/associations.rb +6 -0
  9. data/lib/active_record/attribute_methods/dirty.rb +2 -2
  10. data/lib/active_record/attribute_methods/read.rb +3 -3
  11. data/lib/active_record/attribute_methods/write.rb +3 -3
  12. data/lib/active_record/attribute_methods.rb +46 -6
  13. data/lib/active_record/autosave_association.rb +5 -2
  14. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +8 -1
  15. data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
  16. data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
  17. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +8 -4
  18. data/lib/active_record/connection_adapters/abstract_adapter.rb +14 -15
  19. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +37 -13
  20. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +2 -1
  21. data/lib/active_record/connection_adapters/mysql2_adapter.rb +16 -10
  22. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
  23. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +1 -1
  24. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +2 -2
  25. data/lib/active_record/connection_adapters/trilogy_adapter.rb +16 -20
  26. data/lib/active_record/core.rb +7 -2
  27. data/lib/active_record/counter_cache.rb +7 -3
  28. data/lib/active_record/database_configurations/hash_config.rb +6 -2
  29. data/lib/active_record/delegated_type.rb +6 -6
  30. data/lib/active_record/destroy_association_async_job.rb +1 -1
  31. data/lib/active_record/encryption/encrypted_attribute_type.rb +2 -2
  32. data/lib/active_record/encryption/scheme.rb +8 -4
  33. data/lib/active_record/future_result.rb +9 -0
  34. data/lib/active_record/gem_version.rb +1 -1
  35. data/lib/active_record/locking/optimistic.rb +1 -1
  36. data/lib/active_record/marshalling.rb +1 -1
  37. data/lib/active_record/message_pack.rb +1 -1
  38. data/lib/active_record/migration/compatibility.rb +6 -0
  39. data/lib/active_record/model_schema.rb +6 -2
  40. data/lib/active_record/persistence.rb +2 -2
  41. data/lib/active_record/query_cache.rb +1 -1
  42. data/lib/active_record/query_logs_formatter.rb +1 -1
  43. data/lib/active_record/railtie.rb +10 -13
  44. data/lib/active_record/railties/databases.rake +2 -2
  45. data/lib/active_record/reflection.rb +8 -2
  46. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +6 -1
  47. data/lib/active_record/relation/query_methods.rb +21 -7
  48. data/lib/active_record/relation.rb +13 -3
  49. data/lib/active_record/result.rb +1 -1
  50. data/lib/active_record/tasks/database_tasks.rb +19 -8
  51. data/lib/active_record/test_fixtures.rb +1 -0
  52. data/lib/active_record/timestamp.rb +3 -1
  53. data/lib/active_record.rb +2 -2
  54. data/lib/arel/tree_manager.rb +5 -1
  55. data/lib/arel/visitors/to_sql.rb +2 -1
  56. metadata +13 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c29973d598bdc0ac426db1a97047ba9052c41ec75af68e2264a94ef6bf044a4
4
- data.tar.gz: e419114f0171e99f19dddc824868b6aaf77fea4206b0fbe2e1612bdb3ea0b5d3
3
+ metadata.gz: a200f8abed48ce6ab97abf8451e08f9178d634f1b6186b61ee4a81552e246109
4
+ data.tar.gz: c379bb65f3b1819ed78702da8bb8167ca21c34a9a35d54e67bacff74ce3fefc3
5
5
  SHA512:
6
- metadata.gz: 6d88c9882cffebcaea6515a88c6ca9a79a57ba6b178b1b2079f8d188302dfcdbbe22f554bf14d3052924301385f9e7605185715bacc7c94c3ba534ac0a651cc1
7
- data.tar.gz: eabb2fc6dfd14ac4b525804254f6ce05a982f3a1f31250f049b61f4f87cde4a8ef62469b926873c7f2c5ff82ca5696c58f190373d3ea4a611f8fcdbba1d78111
6
+ metadata.gz: 3a1564536513adb015b00aa10817bc0f672199788ede2b3ff7cef755622fde07c02c3410c6d7f223127998da69cfd2ff3033fef2615bbd778ea3f26dbdf62f1f
7
+ data.tar.gz: 44838c96abc346df10cf6ad6aae9083f09a96345b53cdc78cd216a0db2c2c10a0831c66d8ce17d7e1f11a897c4d9bb8eb81b06dbc231589624565da4275f2f96
data/CHANGELOG.md CHANGED
@@ -1,3 +1,269 @@
1
+ ## Rails 7.1.4.1 (October 15, 2024) ##
2
+
3
+ * No changes.
4
+
5
+
6
+ ## Rails 7.1.4 (August 22, 2024) ##
7
+
8
+ * Allow to eager load nested nil associations.
9
+
10
+ *fatkodima*
11
+
12
+ * Fix `create_table` with `:auto_increment` option for MySQL adapter.
13
+
14
+ *fatkodima*
15
+
16
+ * Don't load has_one associations during autosave.
17
+
18
+ *Eugene Kenny*
19
+
20
+ * Fix migration ordering for `bin/rails db:prepare` across databases.
21
+
22
+ *fatkodima*
23
+
24
+ * Fix `alias_attribute` to ignore methods defined in parent classes.
25
+
26
+ *Jean Boussier*
27
+
28
+ * Fix a performance regression in attribute methods.
29
+
30
+ *Jean Boussier*
31
+
32
+ * Fix Active Record configs variable shadowing.
33
+
34
+ *Joel Lubrano*
35
+
36
+ * Fix running migrations on other databases when `database_tasks: false` on primary.
37
+
38
+ *fatkodima*
39
+
40
+ * Fix non-partial inserts for models with composite identity primary keys.
41
+
42
+ *fatkodima*
43
+
44
+ * Fix `ActiveRecord::Relation#touch_all` with custom attribute aliased as attribute for update.
45
+
46
+ *fatkodima*
47
+
48
+ * Fix a crash when an Executor wrapped fork exit.
49
+
50
+ *Joé Dupuis*
51
+
52
+ * Fix `destroy_async` job for owners with composite primary keys.
53
+
54
+ *fatkodima*
55
+
56
+ * Ensure pre-7.1 migrations use legacy index names when using `rename_table`.
57
+
58
+ *fatkodima*
59
+
60
+ * Allow `primary_key:` association option to be composite.
61
+
62
+ *Nikita Vasilevsky*
63
+
64
+ * Do not try to alias on key update when raw SQL is supplied.
65
+
66
+ *Gabriel Amaral*
67
+
68
+ * Memoize `key_provider` from `key` or deterministic `key_provider` if any.
69
+
70
+ *Rosa Gutierrez*
71
+
72
+ * Fix `upsert` warning for MySQL.
73
+
74
+ *fatkodima*
75
+
76
+ * Fix predicate builder for polymorphic models referencing models with composite primary keys.
77
+
78
+ *fatkodima*
79
+
80
+ * Fix `update_all/delete_all` on CPK model relation with join subquery.
81
+
82
+ *Nikita Vasilevsky*
83
+
84
+ * Remove memoization to accept `key_provider` overridden by `with_encryption_context`.
85
+
86
+ *John Hawthorn*
87
+
88
+ * Raise error for Trilogy when prepared_statements is true.
89
+
90
+ Trilogy doesn't currently support prepared statements. The error that
91
+ applications would see is a `StatementInvalid` error. This doesn't quite point
92
+ you to the fact this isn't supported. So raise a more appropriate error
93
+ pointing to what to change.
94
+
95
+ *Eileen M. Uchitelle*
96
+
97
+ * Fix loading schema cache when all databases have disabled database tasks.
98
+
99
+ *fatkodima*
100
+
101
+ * Always request `primary_key` in `RETURNING` if no other columns requested.
102
+
103
+ *Nikita Vasilevsky*
104
+
105
+ * Handle records being loaded with Marshal without triggering schema load
106
+
107
+ When using the old marshalling format for Active Record and loading
108
+ a serialized instance, it didn't trigger loading the schema and defining
109
+ attribute methods.
110
+
111
+ *Jean Boussier*
112
+
113
+ * Prevent some constant redefinition warnings when defining `inherited` on models.
114
+
115
+ *Adrian Hirt*
116
+
117
+ * Fix a memory perfomance regression in attribute methods.
118
+
119
+ Attribute methods used much more memory and were slower to define than
120
+ they should have been.
121
+
122
+ *Jean Boussier*
123
+
124
+ * Fix an issue that could cause database connection leaks.
125
+
126
+ If Active Record successfully connected to the database, but then failed
127
+ to read the server informations, the connection would be leaked until the
128
+ Ruby garbage collector triggers.
129
+
130
+ *Jean Boussier*
131
+
132
+ * Fix an issue where the IDs reader method did not return expected results
133
+ for preloaded associations in models using composite primary keys.
134
+
135
+ *Jay Ang*
136
+
137
+ * PostgreSQL `Cidr#change?` detects the address prefix change.
138
+
139
+ *Taketo Takashima*
140
+
141
+ * Fix Active Record serialization to not include instantiated but not loaded associations
142
+
143
+ *Jean Boussier*, *Ben Kyriakou*
144
+
145
+ * Allow `Sqlite3Adapter` to use `sqlite3` gem version `2.x`
146
+
147
+ *Mike Dalessio*
148
+
149
+ * Strict loading using `:n_plus_one_only` does not eagerly load child associations.
150
+
151
+ With this change, child associations are no longer eagerly loaded, to
152
+ match intended behavior and to prevent non-deterministic order issues caused
153
+ by calling methods like `first` or `last`. As `first` and `last` don't cause
154
+ an N+1 by themselves, calling child associations will no longer raise.
155
+ Fixes #49473.
156
+
157
+ Before:
158
+
159
+ ```ruby
160
+ person = Person.find(1)
161
+ person.strict_loading!(mode: :n_plus_one_only)
162
+ person.posts.first
163
+ # SELECT * FROM posts WHERE person_id = 1; -- non-deterministic order
164
+ person.posts.first.firm # raises ActiveRecord::StrictLoadingViolationError
165
+ ```
166
+
167
+ After:
168
+
169
+ ```ruby
170
+ person = Person.find(1)
171
+ person.strict_loading!(mode: :n_plus_one_only)
172
+ person.posts.first # this is 1+1, not N+1
173
+ # SELECT * FROM posts WHERE person_id = 1 ORDER BY id LIMIT 1;
174
+ person.posts.first.firm # no longer raises
175
+ ```
176
+
177
+ *Reid Lynch*
178
+
179
+ * Using `Model.query_constraints` with a single non-primary-key column used to raise as expected, but with an
180
+ incorrect error message. This has been fixed to raise with a more appropriate error message.
181
+
182
+ *Joshua Young*
183
+
184
+ * Fix `has_one` association autosave setting the foreign key attribute when it is unchanged.
185
+
186
+ This behaviour is also inconsistent with autosaving `belongs_to` and can have unintended side effects like raising
187
+ an `ActiveRecord::ReadonlyAttributeError` when the foreign key attribute is marked as read-only.
188
+
189
+ *Joshua Young*
190
+
191
+ * Fix an issue where `ActiveRecord::Encryption` configurations are not ready before the loading
192
+ of Active Record models, when an application is eager loaded. As a result, encrypted attributes
193
+ could be misconfigured in some cases.
194
+
195
+ *Maxime Réty*
196
+
197
+ * Properly synchronize `Mysql2Adapter#active?` and `TrilogyAdapter#active?`
198
+
199
+ As well as `disconnect!` and `verify!`.
200
+
201
+ This generally isn't a big problem as connections must not be shared between
202
+ threads, but is required when running transactional tests or system tests
203
+ and could lead to a SEGV.
204
+
205
+ *Jean Boussier*
206
+
207
+ * Fix counter caches when the foreign key is composite.
208
+
209
+ If the model holding the counter cache had a composite primary key,
210
+ inserting a dependent record would fail with an `ArgumentError`
211
+ `Expected corresponding value for...`
212
+
213
+ *fatkodima*
214
+
215
+ * Fix loading of schema cache for multiple databases.
216
+
217
+ Before this change, if you have multiple databases configured in your
218
+ application, and had schema cache present, Rails would load the same
219
+ cache to all databases.
220
+
221
+ *Rafael Mendonça França*
222
+
223
+ * Fix eager loading of composite primary key associations.
224
+
225
+ `relation.eager_load(:other_model)` could load the wrong records if `other_model`
226
+ had a composite primary key.
227
+
228
+ *Nikita Vasilevsky*
229
+
230
+ * Fix async queries returning a doubly wrapped result when hitting the query cache.
231
+
232
+ *fatkodima*
233
+
234
+ * Fix single quote escapes on default generated MySQL columns
235
+
236
+ MySQL 5.7.5+ supports generated columns, which can be used to create a column that is computed from an expression.
237
+
238
+ Previously, the schema dump would output a string with double escapes for generated columns with single quotes in the default expression.
239
+
240
+ This would result in issues when importing the schema on a fresh instance of a MySQL database.
241
+
242
+ Now, the string will not be escaped and will be valid Ruby upon importing of the schema.
243
+
244
+ *Yash Kapadia*
245
+
246
+ * Fix Migrations with versions older than 7.1 validating options given to
247
+ `t.references`.
248
+
249
+ *Hartley McGuire*
250
+
251
+
252
+ ## Rails 7.1.3.4 (June 04, 2024) ##
253
+
254
+ * No changes.
255
+
256
+
257
+ ## Rails 7.1.3.3 (May 16, 2024) ##
258
+
259
+ * No changes.
260
+
261
+
262
+ ## Rails 7.1.3.2 (February 21, 2024) ##
263
+
264
+ * No changes.
265
+
266
+
1
267
  ## Rails 7.1.3.1 (February 21, 2024) ##
2
268
 
3
269
  * No changes.
@@ -12,11 +12,11 @@ module ActiveRecord
12
12
  raise ActiveRecord::Rollback unless target.destroy
13
13
  when :destroy_async
14
14
  if reflection.foreign_key.is_a?(Array)
15
- primary_key_column = reflection.active_record_primary_key.map(&:to_sym)
16
- id = reflection.foreign_key.map { |col| owner.public_send(col.to_sym) }
15
+ primary_key_column = reflection.active_record_primary_key
16
+ id = reflection.foreign_key.map { |col| owner.public_send(col) }
17
17
  else
18
- primary_key_column = reflection.active_record_primary_key.to_sym
19
- id = owner.public_send(reflection.foreign_key.to_sym)
18
+ primary_key_column = reflection.active_record_primary_key
19
+ id = owner.public_send(reflection.foreign_key)
20
20
  end
21
21
 
22
22
  enqueue_destroy_association(
@@ -48,11 +48,11 @@ module ActiveRecord
48
48
  # Implements the ids reader method, e.g. foo.item_ids for Foo.has_many :items
49
49
  def ids_reader
50
50
  if loaded?
51
- target.pluck(reflection.association_primary_key)
51
+ target.pluck(*reflection.association_primary_key)
52
52
  elsif !target.empty?
53
- load_target.pluck(reflection.association_primary_key)
53
+ load_target.pluck(*reflection.association_primary_key)
54
54
  else
55
- @association_ids ||= scope.pluck(reflection.association_primary_key)
55
+ @association_ids ||= scope.pluck(*reflection.association_primary_key)
56
56
  end
57
57
  end
58
58
 
@@ -303,7 +303,7 @@ module ActiveRecord
303
303
 
304
304
  def find_from_target?
305
305
  loaded? ||
306
- owner.strict_loading? ||
306
+ (owner.strict_loading? && owner.strict_loading_all?) ||
307
307
  reflection.strict_loading? ||
308
308
  owner.new_record? ||
309
309
  target.any? { |record| record.new_record? || record.changed? }
@@ -35,10 +35,10 @@ module ActiveRecord
35
35
  unless target.empty?
36
36
  association_class = target.first.class
37
37
  if association_class.query_constraints_list
38
- primary_key_column = association_class.query_constraints_list.map(&:to_sym)
38
+ primary_key_column = association_class.query_constraints_list
39
39
  ids = target.collect { |assoc| primary_key_column.map { |col| assoc.public_send(col) } }
40
40
  else
41
- primary_key_column = association_class.primary_key.to_sym
41
+ primary_key_column = association_class.primary_key
42
42
  ids = target.collect { |assoc| assoc.public_send(primary_key_column) }
43
43
  end
44
44
 
@@ -34,10 +34,10 @@ module ActiveRecord
34
34
  throw(:abort) unless target.destroyed?
35
35
  when :destroy_async
36
36
  if target.class.query_constraints_list
37
- primary_key_column = target.class.query_constraints_list.map(&:to_sym)
37
+ primary_key_column = target.class.query_constraints_list
38
38
  id = primary_key_column.map { |col| target.public_send(col) }
39
39
  else
40
- primary_key_column = target.class.primary_key.to_sym
40
+ primary_key_column = target.class.primary_key
41
41
  id = target.public_send(primary_key_column)
42
42
  end
43
43
 
@@ -61,7 +61,7 @@ module ActiveRecord
61
61
  when Hash
62
62
  associations.each do |k, v|
63
63
  cache = hash[k] ||= {}
64
- walk_tree v, cache
64
+ walk_tree v, cache if v
65
65
  end
66
66
  else
67
67
  raise ConfigurationError, associations.inspect
@@ -254,10 +254,10 @@ module ActiveRecord
254
254
 
255
255
  if node.primary_key
256
256
  keys = Array(node.primary_key).map { |column| aliases.column_alias(node, column) }
257
- ids = keys.map { |key| row[key] }
257
+ id = keys.map { |key| row[key] }
258
258
  else
259
259
  keys = Array(node.reflection.join_primary_key).map { |column| aliases.column_alias(node, column.to_s) }
260
- ids = keys.map { nil } # Avoid id-based model caching.
260
+ id = keys.map { nil } # Avoid id-based model caching.
261
261
  end
262
262
 
263
263
  if keys.any? { |key| row[key].nil? }
@@ -266,11 +266,9 @@ module ActiveRecord
266
266
  next
267
267
  end
268
268
 
269
- ids.each do |id|
270
- unless model = seen[ar_parent][node][id]
271
- model = construct_model(ar_parent, node, row, model_cache, id, strict_loading_value)
272
- seen[ar_parent][node][id] = model if id
273
- end
269
+ unless model = seen[ar_parent][node][id]
270
+ model = construct_model(ar_parent, node, row, model_cache, id, strict_loading_value)
271
+ seen[ar_parent][node][id] = model if id
274
272
  end
275
273
 
276
274
  construct(model, node, row, seen, model_cache, strict_loading_value)
@@ -1506,6 +1506,11 @@ module ActiveRecord
1506
1506
  # Serves as a composite foreign key. Defines the list of columns to be used to query the associated object.
1507
1507
  # This is an optional option. By default Rails will attempt to derive the value automatically.
1508
1508
  # When the value is set the Array size must match associated model's primary key or +query_constraints+ size.
1509
+ # [+:index_errors+]
1510
+ # Enables differentiation of multiple validation errors from the association records, by including
1511
+ # an index in the error attribute name, e.g. +roles[2].level+.
1512
+ # The index is based on association order, i.e. database order, with yet to be
1513
+ # persisted new records placed at the end.
1509
1514
  #
1510
1515
  # Option examples:
1511
1516
  # has_many :comments, -> { order("posted_on") }
@@ -1519,6 +1524,7 @@ module ActiveRecord
1519
1524
  # has_many :subscribers, through: :subscriptions, disable_joins: true
1520
1525
  # has_many :comments, strict_loading: true
1521
1526
  # has_many :comments, query_constraints: [:blog_id, :post_id]
1527
+ # has_many :comments, index_errors: true
1522
1528
  def has_many(name, scope = nil, **options, &extension)
1523
1529
  reflection = Builder::HasMany.build(self, name, scope, options, &extension)
1524
1530
  Reflection.add_reflection self, name, reflection
@@ -31,7 +31,7 @@ module ActiveRecord
31
31
  # person.name_in_database # => "Alice"
32
32
  # person.saved_change_to_name? # => true
33
33
  # person.saved_change_to_name # => ["Allison", "Alice"]
34
- # person.name_before_last_change # => "Allison"
34
+ # person.name_before_last_save # => "Allison"
35
35
  #
36
36
  # Similar to ActiveModel::Dirty, methods can be invoked as
37
37
  # +saved_change_to_name?+ or by passing an argument to the generic method
@@ -251,7 +251,7 @@ module ActiveRecord
251
251
  changed_attribute_names_to_save
252
252
  else
253
253
  attribute_names.reject do |attr_name|
254
- if column_for_attribute(attr_name).default_function
254
+ if column_for_attribute(attr_name).auto_populated?
255
255
  !attribute_changed?(attr_name)
256
256
  end
257
257
  end
@@ -8,11 +8,11 @@ module ActiveRecord
8
8
 
9
9
  module ClassMethods # :nodoc:
10
10
  private
11
- def define_method_attribute(name, owner:)
11
+ def define_method_attribute(canonical_name, owner:, as: canonical_name)
12
12
  ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
13
- owner, name
13
+ owner, canonical_name
14
14
  ) do |temp_method_name, attr_name_expr|
15
- owner.define_cached_method(name, as: temp_method_name, namespace: :active_record) do |batch|
15
+ owner.define_cached_method(temp_method_name, as: as, namespace: :active_record) do |batch|
16
16
  batch <<
17
17
  "def #{temp_method_name}" <<
18
18
  " _read_attribute(#{attr_name_expr}) { |n| missing_attribute(n, caller) }" <<
@@ -12,11 +12,11 @@ module ActiveRecord
12
12
 
13
13
  module ClassMethods # :nodoc:
14
14
  private
15
- def define_method_attribute=(name, owner:)
15
+ def define_method_attribute=(canonical_name, owner:, as: canonical_name)
16
16
  ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
17
- owner, name, writer: true,
17
+ owner, canonical_name, writer: true,
18
18
  ) do |temp_method_name, attr_name_expr|
19
- owner.define_cached_method("#{name}=", as: temp_method_name, namespace: :active_record) do |batch|
19
+ owner.define_cached_method(temp_method_name, as: "#{as}=", namespace: :active_record) do |batch|
20
20
  batch <<
21
21
  "def #{temp_method_name}(value)" <<
22
22
  " _write_attribute(#{attr_name_expr}, value)" <<
@@ -66,7 +66,7 @@ module ActiveRecord
66
66
 
67
67
  def generate_alias_attributes # :nodoc:
68
68
  superclass.generate_alias_attributes unless superclass == Base
69
- return if @alias_attributes_mass_generated
69
+ return false if @alias_attributes_mass_generated
70
70
 
71
71
  generated_attribute_methods.synchronize do
72
72
  return if @alias_attributes_mass_generated
@@ -80,12 +80,19 @@ module ActiveRecord
80
80
 
81
81
  @alias_attributes_mass_generated = true
82
82
  end
83
+ true
83
84
  end
84
85
 
85
- def alias_attribute_method_definition(code_generator, pattern, new_name, old_name)
86
+ def generate_alias_attribute_methods(code_generator, new_name, old_name) # :nodoc:
87
+ attribute_method_patterns.each do |pattern|
88
+ alias_attribute_method_definition(code_generator, pattern, new_name, old_name)
89
+ end
90
+ attribute_method_patterns_cache.clear
91
+ end
92
+
93
+ def alias_attribute_method_definition(code_generator, pattern, new_name, old_name) # :nodoc:
86
94
  method_name = pattern.method_name(new_name).to_s
87
95
  target_name = pattern.method_name(old_name).to_s
88
- parameters = pattern.parameters
89
96
  old_name = old_name.to_s
90
97
 
91
98
  method_defined = method_defined?(target_name) || private_method_defined?(target_name)
@@ -115,9 +122,7 @@ module ActiveRecord
115
122
  )
116
123
  super
117
124
  else
118
- define_proxy_call(code_generator, method_name, pattern.proxy_target, parameters, old_name,
119
- namespace: :proxy_alias_attribute
120
- )
125
+ define_attribute_method_pattern(pattern, old_name, owner: code_generator, as: new_name, override: true)
121
126
  end
122
127
  end
123
128
 
@@ -133,6 +138,11 @@ module ActiveRecord
133
138
  super(attribute_names)
134
139
  @attribute_methods_generated = true
135
140
  end
141
+ true
142
+ end
143
+
144
+ def attribute_methods_generated? # :nodoc:
145
+ @attribute_methods_generated && @alias_attributes_mass_generated
136
146
  end
137
147
 
138
148
  def undefine_attribute_methods # :nodoc:
@@ -459,6 +469,36 @@ module ActiveRecord
459
469
  end
460
470
 
461
471
  private
472
+ def respond_to_missing?(name, include_private = false)
473
+ if self.class.define_attribute_methods
474
+ # Some methods weren't defined yet.
475
+ return true if self.class.method_defined?(name)
476
+ return true if include_private && self.class.private_method_defined?(name)
477
+ end
478
+
479
+ super
480
+ end
481
+
482
+ def method_missing(name, ...)
483
+ unless self.class.attribute_methods_generated?
484
+ if self.class.method_defined?(name)
485
+ # The method is explicitly defined in the model, but calls a generated
486
+ # method with super. So we must resume the call chain at the right setp.
487
+ last_method = method(name)
488
+ last_method = last_method.super_method while last_method.super_method
489
+ self.class.define_attribute_methods
490
+ if last_method.super_method
491
+ return last_method.super_method.call(...)
492
+ end
493
+ elsif self.class.define_attribute_methods | self.class.generate_alias_attributes
494
+ # Some attribute methods weren't generated yet, we retry the call
495
+ return public_send(name, ...)
496
+ end
497
+ end
498
+
499
+ super
500
+ end
501
+
462
502
  def attribute_method?(attr_name)
463
503
  # We check defined? because Syck calls respond_to? before actually calling initialize.
464
504
  defined?(@attributes) && @attributes.key?(attr_name)
@@ -441,7 +441,9 @@ module ActiveRecord
441
441
  # ActiveRecord::Base after the AutosaveAssociation module, which it does by default.
442
442
  def save_has_one_association(reflection)
443
443
  association = association_instance_get(reflection.name)
444
- record = association && association.load_target
444
+ return unless association && association.loaded?
445
+
446
+ record = association.load_target
445
447
 
446
448
  if record && !record.destroyed?
447
449
  autosave = reflection.options[:autosave]
@@ -458,7 +460,8 @@ module ActiveRecord
458
460
  primary_key_foreign_key_pairs = primary_key.zip(foreign_key)
459
461
 
460
462
  primary_key_foreign_key_pairs.each do |primary_key, foreign_key|
461
- record[foreign_key] = _read_attribute(primary_key)
463
+ association_id = _read_attribute(primary_key)
464
+ record[foreign_key] = association_id unless record[foreign_key] == association_id
462
465
  end
463
466
  association.set_inverse_instance(record)
464
467
  end
@@ -675,7 +675,14 @@ module ActiveRecord
675
675
  def new_connection
676
676
  connection = Base.public_send(db_config.adapter_method, db_config.configuration_hash)
677
677
  connection.pool = self
678
- connection.check_version
678
+
679
+ begin
680
+ connection.check_version
681
+ rescue
682
+ connection.disconnect!
683
+ raise
684
+ end
685
+
679
686
  connection
680
687
  rescue ConnectionNotEstablished => ex
681
688
  raise ex.set_pool(self)
@@ -629,7 +629,7 @@ module ActiveRecord
629
629
 
630
630
  result = internal_exec_query(sql, name, binds, prepare: prepare)
631
631
  if async
632
- FutureResult::Complete.new(result)
632
+ FutureResult.wrap(result)
633
633
  else
634
634
  result
635
635
  end
@@ -107,7 +107,7 @@ module ActiveRecord
107
107
 
108
108
  if async
109
109
  result = lookup_sql_cache(sql, name, binds) || super(sql, name, binds, preparable: preparable, async: async)
110
- FutureResult::Complete.new(result)
110
+ FutureResult.wrap(result)
111
111
  else
112
112
  cache_sql(sql, name, binds) { super(sql, name, binds, preparable: preparable, async: async) }
113
113
  end
@@ -963,7 +963,11 @@ module ActiveRecord
963
963
  def index_name(table_name, options) # :nodoc:
964
964
  if Hash === options
965
965
  if options[:column]
966
- generate_index_name(table_name, options[:column])
966
+ if options[:_uses_legacy_index_name]
967
+ "index_#{table_name}_on_#{Array(options[:column]) * '_and_'}"
968
+ else
969
+ generate_index_name(table_name, options[:column])
970
+ end
967
971
  elsif options[:name]
968
972
  options[:name]
969
973
  else
@@ -1636,11 +1640,11 @@ module ActiveRecord
1636
1640
  end
1637
1641
  end
1638
1642
 
1639
- def rename_table_indexes(table_name, new_name)
1643
+ def rename_table_indexes(table_name, new_name, **options)
1640
1644
  indexes(new_name).each do |index|
1641
- generated_index_name = index_name(table_name, column: index.columns)
1645
+ generated_index_name = index_name(table_name, column: index.columns, **options)
1642
1646
  if generated_index_name == index.name
1643
- rename_index new_name, generated_index_name, index_name(new_name, column: index.columns)
1647
+ rename_index new_name, generated_index_name, index_name(new_name, column: index.columns, **options)
1644
1648
  end
1645
1649
  end
1646
1650
  end