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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +266 -0
- data/lib/active_record/associations/belongs_to_association.rb +4 -4
- data/lib/active_record/associations/collection_association.rb +4 -4
- data/lib/active_record/associations/has_many_association.rb +2 -2
- data/lib/active_record/associations/has_one_association.rb +2 -2
- data/lib/active_record/associations/join_dependency.rb +6 -8
- data/lib/active_record/associations.rb +6 -0
- data/lib/active_record/attribute_methods/dirty.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +3 -3
- data/lib/active_record/attribute_methods/write.rb +3 -3
- data/lib/active_record/attribute_methods.rb +46 -6
- data/lib/active_record/autosave_association.rb +5 -2
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +8 -1
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +8 -4
- data/lib/active_record/connection_adapters/abstract_adapter.rb +14 -15
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +37 -13
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +2 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +16 -10
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +2 -2
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +16 -20
- data/lib/active_record/core.rb +7 -2
- data/lib/active_record/counter_cache.rb +7 -3
- data/lib/active_record/database_configurations/hash_config.rb +6 -2
- data/lib/active_record/delegated_type.rb +6 -6
- data/lib/active_record/destroy_association_async_job.rb +1 -1
- data/lib/active_record/encryption/encrypted_attribute_type.rb +2 -2
- data/lib/active_record/encryption/scheme.rb +8 -4
- data/lib/active_record/future_result.rb +9 -0
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +1 -1
- data/lib/active_record/marshalling.rb +1 -1
- data/lib/active_record/message_pack.rb +1 -1
- data/lib/active_record/migration/compatibility.rb +6 -0
- data/lib/active_record/model_schema.rb +6 -2
- data/lib/active_record/persistence.rb +2 -2
- data/lib/active_record/query_cache.rb +1 -1
- data/lib/active_record/query_logs_formatter.rb +1 -1
- data/lib/active_record/railtie.rb +10 -13
- data/lib/active_record/railties/databases.rake +2 -2
- data/lib/active_record/reflection.rb +8 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +6 -1
- data/lib/active_record/relation/query_methods.rb +21 -7
- data/lib/active_record/relation.rb +13 -3
- data/lib/active_record/result.rb +1 -1
- data/lib/active_record/tasks/database_tasks.rb +19 -8
- data/lib/active_record/test_fixtures.rb +1 -0
- data/lib/active_record/timestamp.rb +3 -1
- data/lib/active_record.rb +2 -2
- data/lib/arel/tree_manager.rb +5 -1
- data/lib/arel/visitors/to_sql.rb +2 -1
- metadata +13 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a200f8abed48ce6ab97abf8451e08f9178d634f1b6186b61ee4a81552e246109
|
4
|
+
data.tar.gz: c379bb65f3b1819ed78702da8bb8167ca21c34a9a35d54e67bacff74ce3fefc3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
16
|
-
id = reflection.foreign_key.map { |col| owner.public_send(col
|
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
|
19
|
-
id = owner.public_send(reflection.foreign_key
|
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
|
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
|
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
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
270
|
-
|
271
|
-
|
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.
|
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).
|
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(
|
11
|
+
def define_method_attribute(canonical_name, owner:, as: canonical_name)
|
12
12
|
ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
|
13
|
-
owner,
|
13
|
+
owner, canonical_name
|
14
14
|
) do |temp_method_name, attr_name_expr|
|
15
|
-
owner.define_cached_method(
|
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=(
|
15
|
+
def define_method_attribute=(canonical_name, owner:, as: canonical_name)
|
16
16
|
ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
|
17
|
-
owner,
|
17
|
+
owner, canonical_name, writer: true,
|
18
18
|
) do |temp_method_name, attr_name_expr|
|
19
|
-
owner.define_cached_method("#{
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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)
|
@@ -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
|
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
|
-
|
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
|