activerecord 8.1.3.1 → 8.1.4
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +617 -0
- data/lib/active_record/associations/association.rb +34 -16
- data/lib/active_record/associations/association_scope.rb +1 -1
- data/lib/active_record/associations/belongs_to_association.rb +2 -2
- data/lib/active_record/associations/builder/belongs_to.rb +19 -4
- data/lib/active_record/associations/collection_association.rb +6 -2
- data/lib/active_record/associations/collection_proxy.rb +4 -0
- data/lib/active_record/associations/foreign_association.rb +3 -1
- data/lib/active_record/associations/has_one_association.rb +1 -0
- data/lib/active_record/associations/join_dependency.rb +1 -2
- data/lib/active_record/associations/preloader/association.rb +1 -1
- data/lib/active_record/attribute_methods/serialization.rb +2 -2
- data/lib/active_record/attribute_methods.rb +6 -4
- data/lib/active_record/callbacks.rb +1 -2
- data/lib/active_record/coders/column_serializer.rb +1 -1
- data/lib/active_record/coders/json.rb +7 -6
- data/lib/active_record/coders/yaml_column.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +17 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +32 -20
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +14 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +2 -2
- data/lib/active_record/connection_adapters/abstract_adapter.rb +12 -0
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +79 -23
- data/lib/active_record/connection_adapters/column.rb +2 -5
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +7 -21
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +3 -16
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +46 -3
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +17 -5
- data/lib/active_record/connection_adapters/schema_cache.rb +2 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +2 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +4 -2
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +4 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +14 -0
- data/lib/active_record/counter_cache.rb +8 -6
- data/lib/active_record/database_configurations/hash_config.rb +9 -2
- data/lib/active_record/database_configurations/url_config.rb +2 -0
- data/lib/active_record/disable_joins_association_relation.rb +5 -1
- data/lib/active_record/encryption/encrypted_fixtures.rb +12 -7
- data/lib/active_record/filter_attribute_handler.rb +6 -3
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +8 -3
- data/lib/active_record/log_subscriber.rb +28 -16
- data/lib/active_record/message_pack.rb +13 -0
- data/lib/active_record/migration/command_recorder.rb +12 -2
- data/lib/active_record/model_schema.rb +2 -2
- data/lib/active_record/nested_attributes.rb +8 -6
- data/lib/active_record/persistence.rb +1 -0
- data/lib/active_record/querying.rb +13 -1
- data/lib/active_record/reflection.rb +1 -1
- data/lib/active_record/relation/calculations.rb +8 -3
- data/lib/active_record/relation/finder_methods.rb +34 -20
- data/lib/active_record/relation/merger.rb +4 -2
- data/lib/active_record/relation/predicate_builder.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +63 -13
- data/lib/active_record/relation.rb +20 -12
- data/lib/active_record/schema.rb +1 -1
- data/lib/active_record/schema_dumper.rb +1 -1
- data/lib/active_record/signed_id.rb +1 -1
- data/lib/active_record/statement_cache.rb +1 -1
- data/lib/active_record/store.rb +4 -2
- data/lib/active_record/tasks/abstract_tasks.rb +8 -1
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -16
- data/lib/active_record/test_databases.rb +4 -0
- data/lib/active_record/test_fixtures.rb +13 -4
- data/lib/active_record/transactions.rb +19 -16
- data/lib/active_record/type_caster/connection.rb +1 -1
- data/lib/active_record.rb +1 -1
- data/lib/arel/visitors/to_sql.rb +1 -1
- metadata +9 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5fa58a44daca2d6355264162e3a8f7df6249f432fd3e980b14ffbba7b0aa732c
|
|
4
|
+
data.tar.gz: 706535a8d0930e833eefe7cb2b7e971e0ff1b5297028ced6e53c42a3ae2cd40d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 222277a1c6de4a2c59894eb4c3f1c272482a67ef0eb268edde6c0c70b57e5044c24988273a2a13f1433c3d7f18574e88ad33ea0d994251f01eacdf8b5397c1ae
|
|
7
|
+
data.tar.gz: 476e3611c860d38fed3cee992e8848218f38fd12e505d4463541d1f7015006ef481d224df4263c7f1168f4349e25fa8509ef35dffc9f44858e9e6cf210c99522
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,620 @@
|
|
|
1
|
+
## Rails 8.1.4 (September 24, 2026) ##
|
|
2
|
+
|
|
3
|
+
* Avoid deadlocks when concurrent `find_or_create_by` calls read back the same
|
|
4
|
+
record within MySQL transactions.
|
|
5
|
+
|
|
6
|
+
Use a shared lock for the read after a duplicate insert, preserving visibility
|
|
7
|
+
under REPEATABLE READ without upgrading competing shared locks to exclusive locks.
|
|
8
|
+
This also applies to `create_or_find_by` and the bang variants of both methods.
|
|
9
|
+
|
|
10
|
+
Fixes #54281.
|
|
11
|
+
|
|
12
|
+
*Kirsten Westeinde*
|
|
13
|
+
|
|
14
|
+
* Filter the database password out of failed `db:` task command error messages.
|
|
15
|
+
|
|
16
|
+
*Ngan Pham*
|
|
17
|
+
|
|
18
|
+
* Fix `ActiveRecord::TypeCaster::Connection` sometimes leaking a checked-out
|
|
19
|
+
connection.
|
|
20
|
+
|
|
21
|
+
*Hartley McGuire*
|
|
22
|
+
|
|
23
|
+
* Fix PostgreSQL exclusion constraints with multiline expressions being parsed
|
|
24
|
+
incorrectly during schema introspection.
|
|
25
|
+
|
|
26
|
+
*Jake McAllister*
|
|
27
|
+
|
|
28
|
+
* Fix async `ActiveRecord::StatementCache#execute` raising an error for
|
|
29
|
+
out-of-range bind values instead of returning an empty result.
|
|
30
|
+
|
|
31
|
+
*viralpraxis*
|
|
32
|
+
|
|
33
|
+
* Fix `where` clauses with column-tuple syntax not resolving references to
|
|
34
|
+
other tables.
|
|
35
|
+
|
|
36
|
+
*Chris Gunther*
|
|
37
|
+
|
|
38
|
+
* Fix `distinct: true` being ignored by `average`.
|
|
39
|
+
|
|
40
|
+
*Kenta Ishizaki*
|
|
41
|
+
|
|
42
|
+
* Fix `belongs_to` change tracking for composite foreign keys.
|
|
43
|
+
|
|
44
|
+
Only the first foreign key column was checked for changes; now all foreign
|
|
45
|
+
key columns are checked.
|
|
46
|
+
|
|
47
|
+
*Anas Khan*
|
|
48
|
+
|
|
49
|
+
* Make `add_column(if_not_exists: true)` reversible.
|
|
50
|
+
|
|
51
|
+
*Kenta Ishizaki*
|
|
52
|
+
|
|
53
|
+
* Quote the index name in MySQL `enable_index` and `disable_index`.
|
|
54
|
+
|
|
55
|
+
Unquoted index names containing special characters could cause SQL syntax
|
|
56
|
+
errors.
|
|
57
|
+
|
|
58
|
+
*Kenta Ishizaki*
|
|
59
|
+
|
|
60
|
+
* Make `remove_foreign_key(if_exists: true)` reversible.
|
|
61
|
+
|
|
62
|
+
*Kenta Ishizaki*
|
|
63
|
+
|
|
64
|
+
* Fix `distinct: true` being ignored by grouped `sum`.
|
|
65
|
+
|
|
66
|
+
*Kenta Ishizaki*
|
|
67
|
+
|
|
68
|
+
* Return an `ActiveRecord::Promise` from `async_ids` on a contradictory
|
|
69
|
+
relation, instead of a plain `ActiveRecord::Result`.
|
|
70
|
+
|
|
71
|
+
*Kenta Ishizaki*
|
|
72
|
+
|
|
73
|
+
* Fix reversibility check for `drop_virtual_table`.
|
|
74
|
+
|
|
75
|
+
The wrong argument was extracted, so the check for whether options were
|
|
76
|
+
given could pass or fail incorrectly.
|
|
77
|
+
|
|
78
|
+
*Kenta Ishizaki*
|
|
79
|
+
|
|
80
|
+
* Fix `remove_check_constraint(if_exists: true)` incorrectly raising when
|
|
81
|
+
removing by expression.
|
|
82
|
+
|
|
83
|
+
The `if_exists` check did not pass the expression to
|
|
84
|
+
`check_constraint_exists?`, so it could not find the constraint.
|
|
85
|
+
|
|
86
|
+
*Kenta Ishizaki*
|
|
87
|
+
|
|
88
|
+
* Clear PostgreSQL notices as they are handled, preventing warnings from
|
|
89
|
+
leaking to subsequent queries.
|
|
90
|
+
|
|
91
|
+
*Matthew Draper*
|
|
92
|
+
|
|
93
|
+
* Fix `WeakThreadKeyMap` raising "can't add a new key into hash during
|
|
94
|
+
iteration" when connections are checked in from multiple threads.
|
|
95
|
+
|
|
96
|
+
*Matthew Draper*
|
|
97
|
+
|
|
98
|
+
* Continue pool disconnect after a connection's cleanup or disconnect raises.
|
|
99
|
+
|
|
100
|
+
Previously, a failure on one connection aborted the teardown, stranding
|
|
101
|
+
remaining connections and their resources.
|
|
102
|
+
|
|
103
|
+
*Matthew Draper*
|
|
104
|
+
|
|
105
|
+
* Fix race condition between `preconnect` and the connection pool reaper.
|
|
106
|
+
|
|
107
|
+
*Yasuo Honda*
|
|
108
|
+
|
|
109
|
+
* Fix `in_order_of` raising when the column is a CTE reference.
|
|
110
|
+
|
|
111
|
+
*viralpraxis*
|
|
112
|
+
|
|
113
|
+
* Fix `content_columns` including composite primary key components.
|
|
114
|
+
|
|
115
|
+
Only the first primary key column was excluded; now all primary key columns
|
|
116
|
+
are excluded.
|
|
117
|
+
|
|
118
|
+
*Kenta Ishizaki*
|
|
119
|
+
|
|
120
|
+
* Treat `remove_column` with options but no type as irreversible.
|
|
121
|
+
|
|
122
|
+
Previously, `remove_column(:table, :column, default: nil)` would not raise
|
|
123
|
+
`IrreversibleMigration` because the options hash was mistaken for a column
|
|
124
|
+
type.
|
|
125
|
+
|
|
126
|
+
*Kenta Ishizaki*
|
|
127
|
+
|
|
128
|
+
* Fix `counter_cache_column` crashing when `:counter_cache` is given as a
|
|
129
|
+
Hash without a `:column` key.
|
|
130
|
+
|
|
131
|
+
*Kenta Ishizaki*
|
|
132
|
+
|
|
133
|
+
* Coerce `seeds` and `use_metadata_table` to booleans in `UrlConfig`.
|
|
134
|
+
|
|
135
|
+
When configured via `DATABASE_URL`, these options were left as strings
|
|
136
|
+
instead of being coerced to booleans like `replica` and `database_tasks`.
|
|
137
|
+
|
|
138
|
+
*Kenta Ishizaki*
|
|
139
|
+
|
|
140
|
+
* Fix `excluding` (and its `without` alias) to work with composite primary key
|
|
141
|
+
models. Records passed to `excluding` are now matched by their full composite id
|
|
142
|
+
instead of being looked up by a single primary key column.
|
|
143
|
+
|
|
144
|
+
*Kenta Ishizaki*
|
|
145
|
+
|
|
146
|
+
* Fix `Relation#delete` raising on a single composite primary key id.
|
|
147
|
+
|
|
148
|
+
`Model.delete(id)` now wraps a single composite id in an array before building
|
|
149
|
+
the `WHERE` clause, so a single record can be deleted by its composite id.
|
|
150
|
+
|
|
151
|
+
*Kenta Ishizaki*
|
|
152
|
+
|
|
153
|
+
* Fix reading a composite primary key after a partial `select` returning the
|
|
154
|
+
raw value instead of `nil` for unselected key columns.
|
|
155
|
+
|
|
156
|
+
The attribute defaults builder excluded only the single primary key column from
|
|
157
|
+
defaults; for composite primary keys it left the unselected key columns in the
|
|
158
|
+
defaults, so `record.id` returned an array of raw column values instead of
|
|
159
|
+
`[nil, nil]`. All primary key columns are now excluded.
|
|
160
|
+
|
|
161
|
+
*Kenta Ishizaki*
|
|
162
|
+
|
|
163
|
+
* Fix `find` with an empty array on a composite primary key model returning the
|
|
164
|
+
argument array instead of `[]`.
|
|
165
|
+
|
|
166
|
+
`Model.find([])` now returns a fresh empty array for composite primary key
|
|
167
|
+
models, matching single-key models.
|
|
168
|
+
|
|
169
|
+
*Kenta Ishizaki*
|
|
170
|
+
|
|
171
|
+
* Fix `find` with an order clause and an offset past the end of the ids raising
|
|
172
|
+
`RecordNotFound` instead of returning an empty result.
|
|
173
|
+
|
|
174
|
+
*Kenta Ishizaki*
|
|
175
|
+
|
|
176
|
+
* Fix `in_order_of` dropping values that cannot be serialized for the column
|
|
177
|
+
instead of turning them into an `IS NULL` match.
|
|
178
|
+
|
|
179
|
+
Out-of-range integers and unknown enum keys are now ignored rather than
|
|
180
|
+
silently matching rows with `NULL` in that column. When all requested values
|
|
181
|
+
are unrepresentable, the relation returns no rows instead of building an empty
|
|
182
|
+
`CASE` expression.
|
|
183
|
+
|
|
184
|
+
*Kenta Ishizaki*
|
|
185
|
+
|
|
186
|
+
* Fix stale `finder_needs_type_condition?` memo after the schema cache is reloaded.
|
|
187
|
+
|
|
188
|
+
When an STI model's `type` column was removed and re-added (e.g. via a
|
|
189
|
+
migration) and `reset_column_information` was called, the cached
|
|
190
|
+
`finder_needs_type_condition` value was not cleared, so queries could omit the
|
|
191
|
+
STI type condition. The memo is now reset on `reload_schema_from_cache`.
|
|
192
|
+
|
|
193
|
+
*Kenta Ishizaki*
|
|
194
|
+
|
|
195
|
+
* Fix PostgreSQL schema dump to qualify `enum_type` when the same enum name exists
|
|
196
|
+
in different schemas.
|
|
197
|
+
|
|
198
|
+
Previously the dumped `enum_type` used the bare type name, which could resolve to
|
|
199
|
+
the wrong enum in another schema. It now uses the schema-qualified name.
|
|
200
|
+
|
|
201
|
+
*fatkodima*
|
|
202
|
+
|
|
203
|
+
* Fix PostgreSQL index introspection to parse opclasses from another schema.
|
|
204
|
+
|
|
205
|
+
Index expressions using a schema-qualified opclass (e.g.
|
|
206
|
+
`USING gin(position test_schema.gin_trgm_ops)`) are now parsed correctly so the
|
|
207
|
+
opclass is captured without the schema prefix.
|
|
208
|
+
|
|
209
|
+
*Nicolas Vandenboegaerde*
|
|
210
|
+
|
|
211
|
+
* Fix `belongs_to` `:touch` with composite foreign keys.
|
|
212
|
+
|
|
213
|
+
Touching the parent record when a `belongs_to` with a composite foreign key
|
|
214
|
+
changes or is destroyed now correctly resolves the old and new parent by all
|
|
215
|
+
foreign key columns.
|
|
216
|
+
|
|
217
|
+
*Romulo Storel*
|
|
218
|
+
|
|
219
|
+
* Fix `add_index` `comment:` option on a schema-qualified PostgreSQL table.
|
|
220
|
+
|
|
221
|
+
The `COMMENT ON INDEX` statement now schema-qualifies the index name, so the
|
|
222
|
+
comment is applied to the index in the correct schema instead of raising.
|
|
223
|
+
|
|
224
|
+
*Tobias Egli*
|
|
225
|
+
|
|
226
|
+
* Fix `check_all_foreign_keys_valid!` on PostgreSQL partitioned tables.
|
|
227
|
+
|
|
228
|
+
The validation query previously matched constraints by name across all tables in
|
|
229
|
+
the schema, marking unrelated constraints (including partition children) as not
|
|
230
|
+
validated. It now scopes the update to the specific table.
|
|
231
|
+
|
|
232
|
+
*Alexis Andrieu*
|
|
233
|
+
|
|
234
|
+
* Revert stable sorting of columns and indexes in serialized schema caches.
|
|
235
|
+
|
|
236
|
+
`SchemaCache#encode_with` no longer sorts a table's columns and indexes by name
|
|
237
|
+
when writing the cache, restoring the pre-8.1 behavior.
|
|
238
|
+
|
|
239
|
+
*Jean Boussier*
|
|
240
|
+
|
|
241
|
+
* Fix `only_columns` to enumerate columns in the `SELECT` clause.
|
|
242
|
+
|
|
243
|
+
Models using `only_columns` were generating `SELECT *` instead of an explicit
|
|
244
|
+
column list, which could select columns that were meant to be excluded.
|
|
245
|
+
|
|
246
|
+
*sarub0b0*
|
|
247
|
+
|
|
248
|
+
* Fix `eager_load` with a composite primary key and an explicit `select`.
|
|
249
|
+
|
|
250
|
+
The join dependency used the single primary key value to build aliases; for
|
|
251
|
+
composite primary keys it now uses the full array of primary key columns, so
|
|
252
|
+
eager loading with a custom `select` no longer drops the association records.
|
|
253
|
+
|
|
254
|
+
*fatkodima*
|
|
255
|
+
|
|
256
|
+
* Fix `find_signed` with a composite primary key.
|
|
257
|
+
|
|
258
|
+
`find_signed` now wraps the decoded id in an array so `find_by` matches against
|
|
259
|
+
all primary key columns, instead of silently returning `nil`.
|
|
260
|
+
|
|
261
|
+
*Kenta Ishizaki*
|
|
262
|
+
|
|
263
|
+
* Fix `with_connection(prevent_permanent_checkout: true)` clearing a sticky lease
|
|
264
|
+
that was already set by `lease_connection`.
|
|
265
|
+
|
|
266
|
+
A `with_connection` call with `prevent_permanent_checkout: true` no longer resets
|
|
267
|
+
`lease.sticky` to its previous value when the connection was already sticky, so
|
|
268
|
+
the connection remains checked out after the block.
|
|
269
|
+
|
|
270
|
+
*Ben Sheldon*
|
|
271
|
+
|
|
272
|
+
* Fix `reset_counters` to cast string ids to the primary key type.
|
|
273
|
+
|
|
274
|
+
`reset_counters` called with a string id (the form ids take from request params)
|
|
275
|
+
failed to find the record for both single and composite primary keys. Each id is
|
|
276
|
+
now cast against its own column type.
|
|
277
|
+
|
|
278
|
+
*fatkodima*
|
|
279
|
+
|
|
280
|
+
* Fix `belongs_to` presence validation for composite foreign keys.
|
|
281
|
+
|
|
282
|
+
The required-association validation only checked the first foreign key column.
|
|
283
|
+
For composite foreign keys it now considers the association present only when
|
|
284
|
+
none of the foreign key columns are `nil`, and changed when any of them changed.
|
|
285
|
+
|
|
286
|
+
*Felix Descoteaux*
|
|
287
|
+
|
|
288
|
+
* Fix preloading a `belongs_to` with a composite foreign key when some key columns
|
|
289
|
+
are `nil`.
|
|
290
|
+
|
|
291
|
+
The preloader now skips owners whose composite key has any `nil` component
|
|
292
|
+
instead of issuing a query that matches unrelated rows.
|
|
293
|
+
|
|
294
|
+
*Rose Wiegley*
|
|
295
|
+
|
|
296
|
+
* Fix `belongs_to` inverse matching with composite foreign keys.
|
|
297
|
+
|
|
298
|
+
`inversable?` compared a single foreign key column against a single primary key,
|
|
299
|
+
so `belongs_to` associations with composite foreign keys never matched their
|
|
300
|
+
inverse. Foreign key and primary key values are now compared component by
|
|
301
|
+
component.
|
|
302
|
+
|
|
303
|
+
*Martin Samson*
|
|
304
|
+
|
|
305
|
+
* Fix `validate_table_length!` to ignore the schema prefix on PostgreSQL.
|
|
306
|
+
|
|
307
|
+
Schema-qualified table names (e.g. `"schema.very_long_table_name"`) were
|
|
308
|
+
incorrectly rejected as exceeding the table name length limit because the schema
|
|
309
|
+
prefix was counted. The schema is now stripped before checking the length.
|
|
310
|
+
|
|
311
|
+
*fatkodima*
|
|
312
|
+
|
|
313
|
+
* Fix passing Trilogy SSL options to `mysql` and `mysqldump` commands.
|
|
314
|
+
|
|
315
|
+
*Ngan Pham*
|
|
316
|
+
|
|
317
|
+
* Fix `keepalive: false` in `database.yml` falling back to the
|
|
318
|
+
600 second default.
|
|
319
|
+
|
|
320
|
+
*Joe Sak*
|
|
321
|
+
|
|
322
|
+
* Fix connection checkout blocking past the configured `checkout_timeout` while
|
|
323
|
+
waiting behind background connection maintenance.
|
|
324
|
+
|
|
325
|
+
`ConnectionPool#try_to_queue_for_background_connection` waited up to a
|
|
326
|
+
hardcoded 100 seconds for a connection tied up in maintenance (e.g. a keepalive
|
|
327
|
+
ping), regardless of the pool's configured `checkout_timeout`. If maintenance
|
|
328
|
+
stalled (a slow or unresponsive database server), checkout could block for far
|
|
329
|
+
longer than the caller asked for.
|
|
330
|
+
|
|
331
|
+
*Joe Sak*
|
|
332
|
+
|
|
333
|
+
* Fix encrypted fixtures for JSON columns.
|
|
334
|
+
|
|
335
|
+
Encrypted fixture values were serialized twice: once by the encrypted
|
|
336
|
+
attribute type and again by the column type when the rows were inserted.
|
|
337
|
+
For `json`/`jsonb` columns this stored the encrypted payload as a JSON
|
|
338
|
+
string, which then failed to decrypt. The payload is now handed back in
|
|
339
|
+
the column's cast form so it round-trips through the column type.
|
|
340
|
+
|
|
341
|
+
*Carlos Daniel Pohlod*
|
|
342
|
+
|
|
343
|
+
* Fix performance regression in `method_missing` for virtual SELECT alias
|
|
344
|
+
attributes.
|
|
345
|
+
|
|
346
|
+
Fixes #57183.
|
|
347
|
+
|
|
348
|
+
*Hammad Khan*
|
|
349
|
+
|
|
350
|
+
* Column defaults are no longer eagerly deserialized.
|
|
351
|
+
|
|
352
|
+
Restore the Active Record 8.0 and older behavior.
|
|
353
|
+
Column defaults are now whatever is returned by the database, generally a string.
|
|
354
|
+
|
|
355
|
+
This was changed in 8.1.0 to make the attribute API more consistent,
|
|
356
|
+
however it caused problems when the attribute type is later changed in the model.
|
|
357
|
+
|
|
358
|
+
Typically, some databases treat boolean columns as small integers, ance once the
|
|
359
|
+
default integer is casted to a boolean, it's not longer possible to change the
|
|
360
|
+
attribute back into an integer in the model.
|
|
361
|
+
|
|
362
|
+
Before:
|
|
363
|
+
|
|
364
|
+
```ruby
|
|
365
|
+
Person.columns_hash["age"].default # => 0
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
After:
|
|
369
|
+
|
|
370
|
+
```ruby
|
|
371
|
+
Person.columns_hash["age"].default # => "0"
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
See https://github.com/rails/rails/issues/58292.
|
|
375
|
+
|
|
376
|
+
*Jean Boussier*
|
|
377
|
+
|
|
378
|
+
* Preserve the declared parent order when dumping PostgreSQL `INHERITS` table options.
|
|
379
|
+
|
|
380
|
+
The schema dumper read a table's inherited parents without an `ORDER BY`, so the
|
|
381
|
+
`INHERITS (...)` clause in `schema.rb` could be emitted in a nondeterministic order.
|
|
382
|
+
Parents are now ordered by `pg_inherits.inhseqno`.
|
|
383
|
+
|
|
384
|
+
*viralpraxis*
|
|
385
|
+
|
|
386
|
+
* Preserve SQLite partial and expression indexes when their stored SQL contains newlines.
|
|
387
|
+
|
|
388
|
+
*Javi Ramírez*
|
|
389
|
+
|
|
390
|
+
* Only use multi statement for `SET TRANSACTION ISOLATION LEVEL; BEGIN` if
|
|
391
|
+
MySQL connection is configured to use multi statement.
|
|
392
|
+
|
|
393
|
+
*Eliseu Daroit*, *Hartley McGuire*, *Matthew Draper*
|
|
394
|
+
|
|
395
|
+
* Mark a connection unverified when a non-`StandardError` interrupts a query.
|
|
396
|
+
|
|
397
|
+
A query interrupted by a non-`StandardError`, such as a fiber scheduler's
|
|
398
|
+
cancel or a `Timeout`, leaves the connection desynced. Active Record
|
|
399
|
+
previously returned it to the pool still marked verified, so the next
|
|
400
|
+
checkout reused it and failed on a dead socket. The connection is now
|
|
401
|
+
marked unverified, so it re-verifies and reconnects before its next use.
|
|
402
|
+
|
|
403
|
+
*Eliseu Daroit*
|
|
404
|
+
|
|
405
|
+
* Fix `has_many` and `has_one` associations on a new record returning an empty
|
|
406
|
+
result when the owner has a composite primary key, even when every primary
|
|
407
|
+
key column is populated.
|
|
408
|
+
|
|
409
|
+
*Jean-Samuel Aubry-Guzzi*
|
|
410
|
+
|
|
411
|
+
* Fix inverse association matching for `has_many` and `has_one` associations
|
|
412
|
+
with association-specific composite primary keys.
|
|
413
|
+
|
|
414
|
+
*Hugo Vacher*
|
|
415
|
+
|
|
416
|
+
* Fix `ActiveRecord::Base.with` to call `Object#with` when given a block.
|
|
417
|
+
|
|
418
|
+
The class-level `with` delegates to the relation's CTE query method, which
|
|
419
|
+
does not accept a block. When a block is passed, it now delegates to
|
|
420
|
+
`Object#with` instead, so it can be used to temporarily set attributes on
|
|
421
|
+
the class for the duration of the block.
|
|
422
|
+
|
|
423
|
+
*Janko Marohnić*
|
|
424
|
+
|
|
425
|
+
* Fix `serialize` with `coder: ActiveRecord::Coders::JSON` silently double-encoding
|
|
426
|
+
a native `json`/`jsonb` column.
|
|
427
|
+
|
|
428
|
+
*Kenta Ishizaki*
|
|
429
|
+
|
|
430
|
+
* Fix `update_all` / `delete_all` ignoring `group` and `having`, updating or
|
|
431
|
+
deleting every row in the table instead of only the rows that satisfy the
|
|
432
|
+
`HAVING` clause.
|
|
433
|
+
|
|
434
|
+
*Kenta Ishizaki*
|
|
435
|
+
|
|
436
|
+
* Fix `ActiveRecord::Relation#cache_key` / `cache_version` for a loaded collection
|
|
437
|
+
containing a record without a timestamp.
|
|
438
|
+
|
|
439
|
+
*Kenta Ishizaki*
|
|
440
|
+
|
|
441
|
+
* Fix model `filter_attributes` to not add useless filters into `config.filter_parameters`.
|
|
442
|
+
|
|
443
|
+
Proc and Regexp filters would be improperly turned into string matchers.
|
|
444
|
+
Now they are skipped.
|
|
445
|
+
|
|
446
|
+
*Jonathan Calvert*
|
|
447
|
+
|
|
448
|
+
* Fix `ActiveRecord::MessagePack` serialization raising `NoMethodError`
|
|
449
|
+
for any record with a populated `time` column, which made such records
|
|
450
|
+
uncacheable through the MessagePack cache serializer.
|
|
451
|
+
|
|
452
|
+
*Kenta Ishizaki*
|
|
453
|
+
|
|
454
|
+
* Fix replacing or clearing a polymorphic `has_one` leaving a stale type column
|
|
455
|
+
on the removed record.
|
|
456
|
+
|
|
457
|
+
*Kenta Ishizaki*
|
|
458
|
+
|
|
459
|
+
* Fix `accepts_nested_attributes_for` `:limit` miscounting a single-record hash.
|
|
460
|
+
|
|
461
|
+
*Kenta Ishizaki*
|
|
462
|
+
|
|
463
|
+
* Fix `rename_index` to preserve a partial index's `WHERE` for SQLite and older MySQL/MariaDB versions.
|
|
464
|
+
|
|
465
|
+
*Kenta Ishizaki*
|
|
466
|
+
|
|
467
|
+
* Fix PostgreSQL `foreign_keys` returning a corrupted `to_table` for a foreign key
|
|
468
|
+
that references a table in a quoted schema.
|
|
469
|
+
|
|
470
|
+
*Kenta Ishizaki*
|
|
471
|
+
|
|
472
|
+
* Fix grouped calculations (e.g. `count`) grouped by a `belongs_to` association
|
|
473
|
+
that points to a composite primary key model.
|
|
474
|
+
|
|
475
|
+
`Book.group(:order).count`, where `Book belongs_to :order` and `Order` has a
|
|
476
|
+
composite primary key, raised `ArgumentError: Expected corresponding value
|
|
477
|
+
for ["shop_id", "id"] to be an Array`. The grouped result is now keyed by the
|
|
478
|
+
associated records as it already is for single-column keys.
|
|
479
|
+
|
|
480
|
+
*Kenta Ishizaki*
|
|
481
|
+
|
|
482
|
+
* Fix `has_many`/`has_one :through` associations with `disable_joins: true`
|
|
483
|
+
silently returning an empty result when the source points to a composite
|
|
484
|
+
primary key model.
|
|
485
|
+
|
|
486
|
+
*Kenta Ishizaki*
|
|
487
|
+
|
|
488
|
+
* Fix collection association `ids=` writers (e.g. `author.book_ids=`) raising
|
|
489
|
+
`ActiveRecord::RecordNotFound` for existing records when a composite primary
|
|
490
|
+
key model is assigned string ids (the shape ids take from request params).
|
|
491
|
+
|
|
492
|
+
Each id component is now cast against its own column type, instead of casting
|
|
493
|
+
the whole tuple against an array of column names, which `type_for_attribute`
|
|
494
|
+
can't resolve to a real type (so the cast was a no-op and the string ids
|
|
495
|
+
never matched the loaded records).
|
|
496
|
+
|
|
497
|
+
*Kenta Ishizaki*
|
|
498
|
+
|
|
499
|
+
* Fix `find` with multiple composite primary key ids passed as strings
|
|
500
|
+
silently returning `[]`.
|
|
501
|
+
|
|
502
|
+
`Model.find([["1", "10"], ["1", "20"]])` (the shape ids take when they come
|
|
503
|
+
from request parameters) returned an empty array instead of the records and
|
|
504
|
+
without raising `RecordNotFound`. The ids were cast against the array of key
|
|
505
|
+
column names as a whole — which is a no-op — so the string tuples never
|
|
506
|
+
compared equal to the records' integer ids when ordering the result. Each
|
|
507
|
+
component is now cast against its own column type, matching the documented
|
|
508
|
+
coercion already performed for single-column keys.
|
|
509
|
+
|
|
510
|
+
*Kenta Ishizaki*
|
|
511
|
+
|
|
512
|
+
* Fix PostgreSQL `daterange` / `tsrange` / `tstzrange` schema dump producing
|
|
513
|
+
invalid Ruby.
|
|
514
|
+
|
|
515
|
+
The schema dumper used to render range defaults via `Range#inspect`, which
|
|
516
|
+
falls back to `Date#inspect` / `Time#inspect` for the bounds. The resulting
|
|
517
|
+
`schema.rb` literal (for example `default: Mon, 01 Jan 2024..Wed, 01 Jan 2025`)
|
|
518
|
+
raised a `SyntaxError` on `db:schema:load`. The bounds are now rendered via
|
|
519
|
+
the subtype's `type_cast_for_schema`, so date and timestamp range defaults
|
|
520
|
+
round-trip through `schema.rb` like any other column.
|
|
521
|
+
|
|
522
|
+
*Kenta Ishizaki*
|
|
523
|
+
|
|
524
|
+
* Fix deadlock when pool-less connection materializes while fetching database
|
|
525
|
+
server version.
|
|
526
|
+
|
|
527
|
+
*Hartley McGuire*
|
|
528
|
+
|
|
529
|
+
* Fix PostgreSQL range columns corrupting bounds that contain a comma.
|
|
530
|
+
|
|
531
|
+
`PostgreSQL::OID::Range#extract_bounds` split a range's textual
|
|
532
|
+
representation on the first comma, but PostgreSQL double-quotes any bound
|
|
533
|
+
that itself contains a comma (e.g. a range over a text subtype). A value
|
|
534
|
+
such as `["a,b","c,d")` was therefore split inside the first quoted bound
|
|
535
|
+
and read back with both endpoints corrupted. The split now skips over
|
|
536
|
+
double-quoted segments when locating the separating comma.
|
|
537
|
+
|
|
538
|
+
*Kenta Ishizaki*
|
|
539
|
+
|
|
540
|
+
* Fix store accessor `*_change` and `saved_change_to_*` reporting a change
|
|
541
|
+
for unchanged keys.
|
|
542
|
+
|
|
543
|
+
When one key of a `store` column changed, the generated `<key>_change` and
|
|
544
|
+
`saved_change_to_<key>` methods returned a `[value, value]` pair for the
|
|
545
|
+
column's *other* keys too, even though their matching `<key>_changed?` /
|
|
546
|
+
`saved_change_to_<key>?` correctly returned `false` and standard attribute
|
|
547
|
+
`_change` / `saved_change_to_*` methods return `nil` when unchanged. The
|
|
548
|
+
methods now return `nil` unless that specific key actually changed,
|
|
549
|
+
matching their predicate counterparts.
|
|
550
|
+
|
|
551
|
+
*Kenta Ishizaki*
|
|
552
|
+
|
|
553
|
+
* Reduce number of queries when introspecting MySQL/MariaDB tables.
|
|
554
|
+
|
|
555
|
+
A fix to support MariaDB function defaults caused the MySQL adapters to
|
|
556
|
+
issue one query per column when introspecting tables.
|
|
557
|
+
|
|
558
|
+
Now it only issue a single extra query per table, and only when using MariaDB.
|
|
559
|
+
|
|
560
|
+
*Iliana Hadzhiatanasova*
|
|
561
|
+
|
|
562
|
+
* Fully qualify query criterias in `has_and_belongs_to_many` associations.
|
|
563
|
+
|
|
564
|
+
Ensure that scopes with the same column name but in different tables aren't lost
|
|
565
|
+
when following an HABTM association.
|
|
566
|
+
|
|
567
|
+
*Philip Maina*
|
|
568
|
+
|
|
569
|
+
* Fix Active Record Pool Reaper thread leak after `Parallelization#shutdown`.
|
|
570
|
+
|
|
571
|
+
After parallelized test runs, the parent process leaked the Active Record Pool
|
|
572
|
+
Reaper thread, holding open connection pools and file descriptors for up to
|
|
573
|
+
`reaping_frequency` seconds (or indefinitely if never reaped).
|
|
574
|
+
|
|
575
|
+
Three fixes: `Parallelization#shutdown` now calls `run_cleanup_hooks`;
|
|
576
|
+
Active Record registers a cleanup hook that discards all connection pools; and
|
|
577
|
+
`ConnectionPool#discard!` now calls `Reaper.discard_pool`, which immediately
|
|
578
|
+
kills and joins the reaper thread when no pools remain at that frequency.
|
|
579
|
+
|
|
580
|
+
*Ruy Rocha*
|
|
581
|
+
|
|
582
|
+
* Fix duplicate `WHERE` conditions in `create_or_find_by`.
|
|
583
|
+
|
|
584
|
+
When `create_or_find_by` catches a `RecordNotUnique` error and retries the query, it now uses `rewhere` and `take!` to prevent duplicating existing scope conditions.
|
|
585
|
+
|
|
586
|
+
*Yavor Dashev*
|
|
587
|
+
|
|
588
|
+
* Fix `ActiveRecord::QueryMethods#in_order_of` when passing an out-of-range Integer
|
|
589
|
+
|
|
590
|
+
To match the behavior of the `Enumerable` version, `in_order_of` now ignores an out-of-range Integer.
|
|
591
|
+
|
|
592
|
+
*tejanium*
|
|
593
|
+
|
|
594
|
+
* Revert alphabetical sorting of table columns inside `schema.rb`.
|
|
595
|
+
|
|
596
|
+
Alphabetical sorting of table columns inside the schema creates improper production tables when using `db:prepare`.
|
|
597
|
+
|
|
598
|
+
*Bert McCutchen*
|
|
599
|
+
|
|
600
|
+
* Fix `strict_loading` violations ignored when using `pluck`
|
|
601
|
+
|
|
602
|
+
*Johnson Chan*
|
|
603
|
+
|
|
604
|
+
* Fix incorrect callback execution order when `config.active_record.run_after_transaction_callbacks_in_order_defined = true`
|
|
605
|
+
and using `after_commit` and `after_rollback` callbacks with `prepend: true`.
|
|
606
|
+
|
|
607
|
+
*Joshua Young*
|
|
608
|
+
|
|
609
|
+
* Fix `becomes` to preserve `marked_for_destruction?`.
|
|
610
|
+
|
|
611
|
+
*Vincent Robert*
|
|
612
|
+
|
|
613
|
+
* MySQL error 1046 (`ER_NO_DB_ERROR: No database selected`) is now retryable as a `ConnectionFailed` exception
|
|
614
|
+
|
|
615
|
+
*Clay Harmon*
|
|
616
|
+
|
|
617
|
+
|
|
1
618
|
## Rails 8.1.3.1 (July 29, 2026) ##
|
|
2
619
|
|
|
3
620
|
* No changes.
|
|
@@ -232,6 +232,18 @@ module ActiveRecord
|
|
|
232
232
|
_create_record(attributes, true, &block)
|
|
233
233
|
end
|
|
234
234
|
|
|
235
|
+
def violates_strict_loading?
|
|
236
|
+
return unless find_target?
|
|
237
|
+
|
|
238
|
+
return if @skip_strict_loading
|
|
239
|
+
|
|
240
|
+
return unless owner.validation_context.nil?
|
|
241
|
+
|
|
242
|
+
return reflection.strict_loading? if reflection.options.key?(:strict_loading)
|
|
243
|
+
|
|
244
|
+
owner.strict_loading? && !owner.strict_loading_n_plus_one_only?
|
|
245
|
+
end
|
|
246
|
+
|
|
235
247
|
# Whether the association represents a single record
|
|
236
248
|
# or a collection of records.
|
|
237
249
|
def collection?
|
|
@@ -281,16 +293,6 @@ module ActiveRecord
|
|
|
281
293
|
@skip_strict_loading = skip_strict_loading_was
|
|
282
294
|
end
|
|
283
295
|
|
|
284
|
-
def violates_strict_loading?
|
|
285
|
-
return if @skip_strict_loading
|
|
286
|
-
|
|
287
|
-
return unless owner.validation_context.nil?
|
|
288
|
-
|
|
289
|
-
return reflection.strict_loading? if reflection.options.key?(:strict_loading)
|
|
290
|
-
|
|
291
|
-
owner.strict_loading? && !owner.strict_loading_n_plus_one_only?
|
|
292
|
-
end
|
|
293
|
-
|
|
294
296
|
# The scope for this association.
|
|
295
297
|
#
|
|
296
298
|
# Note that the association_scope is merged into the target_scope only when the
|
|
@@ -409,12 +411,28 @@ module ActiveRecord
|
|
|
409
411
|
end
|
|
410
412
|
|
|
411
413
|
def matches_foreign_key?(record)
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
414
|
+
(foreign_key_for?(record) && record_foreign_key_matches_owner?(record)) ||
|
|
415
|
+
(foreign_key_for?(owner) && owner_foreign_key_matches_record?(record))
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
def record_foreign_key_matches_owner?(record)
|
|
419
|
+
foreign_key_values(record) == active_record_primary_key_values(owner)
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
def owner_foreign_key_matches_record?(record)
|
|
423
|
+
foreign_key_values(owner) == association_primary_key_values(record)
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
def foreign_key_values(record)
|
|
427
|
+
Array(reflection.foreign_key).map { |key| record.read_attribute(key) }
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
def active_record_primary_key_values(record)
|
|
431
|
+
Array(reflection.active_record_primary_key).map { |key| record.read_attribute(key) }
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
def association_primary_key_values(record)
|
|
435
|
+
Array(reflection.association_primary_key(record.class)).map { |key| record.read_attribute(key) }
|
|
418
436
|
end
|
|
419
437
|
end
|
|
420
438
|
end
|