activerecord 8.0.0 → 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 +1381 -241
- data/README.rdoc +2 -2
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/alias_tracker.rb +6 -4
- data/lib/active_record/associations/association.rb +35 -17
- data/lib/active_record/associations/association_scope.rb +1 -1
- data/lib/active_record/associations/belongs_to_association.rb +20 -4
- data/lib/active_record/associations/builder/association.rb +16 -5
- data/lib/active_record/associations/builder/belongs_to.rb +36 -8
- data/lib/active_record/associations/builder/collection_association.rb +7 -3
- data/lib/active_record/associations/builder/has_one.rb +1 -1
- data/lib/active_record/associations/builder/singular_association.rb +33 -5
- data/lib/active_record/associations/collection_association.rb +9 -5
- data/lib/active_record/associations/collection_proxy.rb +26 -4
- data/lib/active_record/associations/deprecation.rb +88 -0
- data/lib/active_record/associations/errors.rb +3 -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/join_association.rb +25 -27
- data/lib/active_record/associations/join_dependency.rb +5 -4
- data/lib/active_record/associations/preloader/association.rb +1 -1
- data/lib/active_record/associations/preloader/batch.rb +7 -1
- data/lib/active_record/associations/preloader/branch.rb +1 -0
- data/lib/active_record/associations.rb +159 -21
- data/lib/active_record/attribute_methods/primary_key.rb +2 -1
- data/lib/active_record/attribute_methods/query.rb +34 -0
- data/lib/active_record/attribute_methods/serialization.rb +19 -6
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +10 -2
- data/lib/active_record/attribute_methods.rb +24 -17
- data/lib/active_record/attributes.rb +40 -26
- data/lib/active_record/autosave_association.rb +22 -12
- data/lib/active_record/base.rb +3 -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 +16 -6
- data/lib/active_record/coders/yaml_column.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +19 -18
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +16 -3
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +68 -12
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +474 -112
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +68 -41
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +36 -9
- data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -24
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +7 -2
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +31 -35
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +94 -28
- data/lib/active_record/connection_adapters/abstract/transaction.rb +25 -3
- data/lib/active_record/connection_adapters/abstract_adapter.rb +166 -64
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +133 -40
- data/lib/active_record/connection_adapters/column.rb +14 -4
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -4
- data/lib/active_record/connection_adapters/mysql/quoting.rb +7 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +42 -5
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +40 -25
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +66 -15
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +9 -3
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +29 -33
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +46 -3
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +21 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +8 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +22 -33
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +70 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +99 -54
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +40 -12
- data/lib/active_record/connection_adapters/sqlite3/column.rb +8 -2
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +39 -23
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +13 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +15 -3
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +7 -14
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +68 -37
- data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +8 -3
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +16 -2
- data/lib/active_record/connection_adapters.rb +1 -0
- data/lib/active_record/connection_handling.rb +15 -10
- data/lib/active_record/core.rb +44 -12
- data/lib/active_record/counter_cache.rb +36 -9
- data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -1
- data/lib/active_record/database_configurations/database_config.rb +5 -1
- data/lib/active_record/database_configurations/hash_config.rb +66 -9
- data/lib/active_record/database_configurations/url_config.rb +15 -3
- data/lib/active_record/database_configurations.rb +7 -3
- data/lib/active_record/delegated_type.rb +19 -19
- data/lib/active_record/disable_joins_association_relation.rb +5 -1
- data/lib/active_record/dynamic_matchers.rb +54 -69
- data/lib/active_record/encryption/encryptable_record.rb +5 -5
- data/lib/active_record/encryption/encrypted_attribute_type.rb +2 -2
- data/lib/active_record/encryption/encrypted_fixtures.rb +12 -7
- data/lib/active_record/encryption/encryptor.rb +39 -25
- data/lib/active_record/encryption/scheme.rb +1 -1
- data/lib/active_record/enum.rb +37 -20
- data/lib/active_record/errors.rb +23 -7
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/explain_registry.rb +51 -2
- data/lib/active_record/filter_attribute_handler.rb +76 -0
- data/lib/active_record/fixture_set/table_row.rb +19 -2
- data/lib/active_record/fixtures.rb +2 -2
- data/lib/active_record/future_result.rb +5 -3
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +9 -4
- data/lib/active_record/insert_all.rb +14 -9
- data/lib/active_record/locking/optimistic.rb +7 -0
- data/lib/active_record/locking/pessimistic.rb +5 -0
- data/lib/active_record/log_subscriber.rb +30 -22
- data/lib/active_record/message_pack.rb +13 -0
- data/lib/active_record/middleware/shard_selector.rb +34 -17
- data/lib/active_record/migration/command_recorder.rb +32 -6
- data/lib/active_record/migration/compatibility.rb +34 -24
- data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
- data/lib/active_record/migration.rb +31 -21
- data/lib/active_record/model_schema.rb +38 -12
- data/lib/active_record/nested_attributes.rb +10 -6
- data/lib/active_record/persistence.rb +35 -3
- data/lib/active_record/query_cache.rb +22 -15
- data/lib/active_record/query_logs.rb +7 -7
- data/lib/active_record/querying.rb +17 -5
- data/lib/active_record/railtie.rb +35 -6
- data/lib/active_record/railties/controller_runtime.rb +11 -6
- data/lib/active_record/railties/databases.rake +24 -20
- data/lib/active_record/railties/job_checkpoints.rb +15 -0
- data/lib/active_record/railties/job_runtime.rb +10 -11
- data/lib/active_record/reflection.rb +36 -1
- data/lib/active_record/relation/batches.rb +25 -11
- data/lib/active_record/relation/calculations.rb +62 -41
- data/lib/active_record/relation/delegation.rb +0 -1
- data/lib/active_record/relation/finder_methods.rb +76 -45
- data/lib/active_record/relation/merger.rb +4 -2
- data/lib/active_record/relation/predicate_builder/array_handler.rb +3 -1
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -9
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +7 -7
- data/lib/active_record/relation/predicate_builder.rb +10 -8
- data/lib/active_record/relation/query_attribute.rb +4 -2
- data/lib/active_record/relation/query_methods.rb +106 -45
- data/lib/active_record/relation/spawn_methods.rb +6 -6
- data/lib/active_record/relation/where_clause.rb +10 -11
- data/lib/active_record/relation.rb +63 -31
- data/lib/active_record/result.rb +44 -21
- data/lib/active_record/runtime_registry.rb +42 -58
- data/lib/active_record/sanitization.rb +2 -0
- data/lib/active_record/schema.rb +1 -1
- data/lib/active_record/schema_dumper.rb +41 -21
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/secure_token.rb +3 -3
- data/lib/active_record/signed_id.rb +48 -19
- data/lib/active_record/statement_cache.rb +16 -12
- data/lib/active_record/store.rb +46 -19
- data/lib/active_record/structured_event_subscriber.rb +85 -0
- data/lib/active_record/table_metadata.rb +5 -20
- data/lib/active_record/tasks/abstract_tasks.rb +83 -0
- data/lib/active_record/tasks/database_tasks.rb +44 -45
- data/lib/active_record/tasks/mysql_database_tasks.rb +4 -56
- data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -40
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -26
- data/lib/active_record/test_databases.rb +18 -4
- data/lib/active_record/test_fixtures.rb +40 -6
- data/lib/active_record/testing/query_assertions.rb +8 -2
- data/lib/active_record/timestamp.rb +4 -2
- data/lib/active_record/transaction.rb +2 -5
- data/lib/active_record/transactions.rb +58 -32
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -1
- data/lib/active_record/type/internal/timezone.rb +7 -0
- data/lib/active_record/type/json.rb +13 -2
- data/lib/active_record/type/serialized.rb +16 -4
- data/lib/active_record/type/type_map.rb +1 -1
- data/lib/active_record/type_caster/connection.rb +2 -1
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record.rb +72 -7
- data/lib/arel/alias_predication.rb +2 -0
- data/lib/arel/collectors/bind.rb +1 -1
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +2 -2
- data/lib/arel/crud.rb +8 -11
- data/lib/arel/delete_manager.rb +5 -0
- data/lib/arel/nodes/binary.rb +1 -1
- data/lib/arel/nodes/count.rb +2 -2
- data/lib/arel/nodes/delete_statement.rb +4 -2
- data/lib/arel/nodes/function.rb +4 -10
- data/lib/arel/nodes/named_function.rb +2 -2
- data/lib/arel/nodes/node.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +1 -1
- data/lib/arel/nodes/update_statement.rb +4 -2
- data/lib/arel/nodes.rb +0 -2
- data/lib/arel/predications.rb +1 -3
- data/lib/arel/select_manager.rb +13 -4
- data/lib/arel/update_manager.rb +5 -0
- data/lib/arel/visitors/dot.rb +2 -3
- data/lib/arel/visitors/postgresql.rb +55 -0
- data/lib/arel/visitors/sqlite.rb +55 -8
- data/lib/arel/visitors/to_sql.rb +7 -23
- data/lib/arel.rb +3 -1
- data/lib/rails/generators/active_record/application_record/USAGE +1 -1
- metadata +16 -15
- data/lib/active_record/explain_subscriber.rb +0 -34
- data/lib/active_record/normalization.rb +0 -163
data/CHANGELOG.md
CHANGED
|
@@ -1,454 +1,1594 @@
|
|
|
1
|
-
## Rails 8.
|
|
1
|
+
## Rails 8.1.4 (September 24, 2026) ##
|
|
2
2
|
|
|
3
|
-
*
|
|
3
|
+
* Avoid deadlocks when concurrent `find_or_create_by` calls read back the same
|
|
4
|
+
record within MySQL transactions.
|
|
4
5
|
|
|
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.
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
Fixes #54281.
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
*Kirsten Westeinde*
|
|
10
13
|
|
|
11
|
-
*
|
|
14
|
+
* Filter the database password out of failed `db:` task command error messages.
|
|
12
15
|
|
|
13
|
-
*
|
|
16
|
+
*Ngan Pham*
|
|
14
17
|
|
|
15
|
-
*
|
|
18
|
+
* Fix `ActiveRecord::TypeCaster::Connection` sometimes leaking a checked-out
|
|
19
|
+
connection.
|
|
16
20
|
|
|
17
|
-
|
|
18
|
-
is created, leading to potential loss of data if a database is added to an
|
|
19
|
-
existing environment.
|
|
21
|
+
*Hartley McGuire*
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
configs and `false` otherwise.
|
|
23
|
+
* Fix PostgreSQL exclusion constraints with multiline expressions being parsed
|
|
24
|
+
incorrectly during schema introspection.
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
*Jake McAllister*
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
* Fix async `ActiveRecord::StatementCache#execute` raising an error for
|
|
29
|
+
out-of-range bind values instead of returning an empty result.
|
|
28
30
|
|
|
29
|
-
*
|
|
31
|
+
*viralpraxis*
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
* Fix `where` clauses with column-tuple syntax not resolving references to
|
|
34
|
+
other tables.
|
|
32
35
|
|
|
33
|
-
*
|
|
36
|
+
*Chris Gunther*
|
|
34
37
|
|
|
35
|
-
|
|
38
|
+
* Fix `distinct: true` being ignored by `average`.
|
|
36
39
|
|
|
37
|
-
*
|
|
40
|
+
*Kenta Ishizaki*
|
|
38
41
|
|
|
39
|
-
|
|
42
|
+
* Fix `belongs_to` change tracking for composite foreign keys.
|
|
40
43
|
|
|
44
|
+
Only the first foreign key column was checked for changes; now all foreign
|
|
45
|
+
key columns are checked.
|
|
41
46
|
|
|
42
|
-
|
|
47
|
+
*Anas Khan*
|
|
43
48
|
|
|
44
|
-
*
|
|
49
|
+
* Make `add_column(if_not_exists: true)` reversible.
|
|
45
50
|
|
|
46
|
-
*
|
|
51
|
+
*Kenta Ishizaki*
|
|
47
52
|
|
|
48
|
-
*
|
|
53
|
+
* Quote the index name in MySQL `enable_index` and `disable_index`.
|
|
49
54
|
|
|
50
|
-
|
|
55
|
+
Unquoted index names containing special characters could cause SQL syntax
|
|
56
|
+
errors.
|
|
51
57
|
|
|
52
|
-
*
|
|
58
|
+
*Kenta Ishizaki*
|
|
53
59
|
|
|
54
|
-
|
|
60
|
+
* Make `remove_foreign_key(if_exists: true)` reversible.
|
|
55
61
|
|
|
56
|
-
*
|
|
62
|
+
*Kenta Ishizaki*
|
|
57
63
|
|
|
58
|
-
|
|
64
|
+
* Fix `distinct: true` being ignored by grouped `sum`.
|
|
59
65
|
|
|
60
|
-
*
|
|
66
|
+
*Kenta Ishizaki*
|
|
61
67
|
|
|
62
|
-
|
|
68
|
+
* Return an `ActiveRecord::Promise` from `async_ids` on a contradictory
|
|
69
|
+
relation, instead of a plain `ActiveRecord::Result`.
|
|
63
70
|
|
|
64
|
-
*
|
|
71
|
+
*Kenta Ishizaki*
|
|
65
72
|
|
|
66
|
-
|
|
73
|
+
* Fix reversibility check for `drop_virtual_table`.
|
|
67
74
|
|
|
68
|
-
|
|
75
|
+
The wrong argument was extracted, so the check for whether options were
|
|
76
|
+
given could pass or fail incorrectly.
|
|
69
77
|
|
|
70
|
-
*
|
|
78
|
+
*Kenta Ishizaki*
|
|
71
79
|
|
|
72
|
-
*
|
|
80
|
+
* Fix `remove_check_constraint(if_exists: true)` incorrectly raising when
|
|
81
|
+
removing by expression.
|
|
73
82
|
|
|
74
|
-
|
|
83
|
+
The `if_exists` check did not pass the expression to
|
|
84
|
+
`check_constraint_exists?`, so it could not find the constraint.
|
|
75
85
|
|
|
76
|
-
*
|
|
86
|
+
*Kenta Ishizaki*
|
|
77
87
|
|
|
78
|
-
|
|
88
|
+
* Clear PostgreSQL notices as they are handled, preventing warnings from
|
|
89
|
+
leaking to subsequent queries.
|
|
79
90
|
|
|
80
|
-
*
|
|
91
|
+
*Matthew Draper*
|
|
81
92
|
|
|
82
|
-
|
|
93
|
+
* Fix `WeakThreadKeyMap` raising "can't add a new key into hash during
|
|
94
|
+
iteration" when connections are checked in from multiple threads.
|
|
83
95
|
|
|
84
|
-
*
|
|
85
|
-
specified.
|
|
96
|
+
*Matthew Draper*
|
|
86
97
|
|
|
87
|
-
|
|
98
|
+
* Continue pool disconnect after a connection's cleanup or disconnect raises.
|
|
88
99
|
|
|
89
|
-
|
|
100
|
+
Previously, a failure on one connection aborted the teardown, stranding
|
|
101
|
+
remaining connections and their resources.
|
|
90
102
|
|
|
91
|
-
*
|
|
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.
|
|
92
220
|
|
|
93
|
-
|
|
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:
|
|
94
363
|
|
|
95
364
|
```ruby
|
|
96
|
-
|
|
97
|
-
Post.joins(:comments).pluck("id", "comments" => "id")
|
|
365
|
+
Person.columns_hash["age"].default # => 0
|
|
98
366
|
```
|
|
99
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
|
+
|
|
100
607
|
*Joshua Young*
|
|
101
608
|
|
|
102
|
-
*
|
|
609
|
+
* Fix `becomes` to preserve `marked_for_destruction?`.
|
|
103
610
|
|
|
104
|
-
|
|
611
|
+
*Vincent Robert*
|
|
105
612
|
|
|
106
|
-
|
|
613
|
+
* MySQL error 1046 (`ER_NO_DB_ERROR: No database selected`) is now retryable as a `ConnectionFailed` exception
|
|
107
614
|
|
|
615
|
+
*Clay Harmon*
|
|
108
616
|
|
|
109
|
-
## Rails 8.0.0.beta1 (September 26, 2024) ##
|
|
110
617
|
|
|
111
|
-
|
|
618
|
+
## Rails 8.1.3.1 (July 29, 2026) ##
|
|
112
619
|
|
|
113
|
-
|
|
620
|
+
* No changes.
|
|
114
621
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
622
|
+
|
|
623
|
+
## Rails 8.1.3 (March 24, 2026) ##
|
|
624
|
+
|
|
625
|
+
* Fix `insert_all` and `upsert_all` log message when called on anonymous classes.
|
|
118
626
|
|
|
119
627
|
*Gabriel Sobrinho*
|
|
120
628
|
|
|
121
|
-
*
|
|
122
|
-
on the `add_enum_value` method.
|
|
629
|
+
* Respect `ActiveRecord::SchemaDumper.ignore_tables` when dumping SQLite virtual tables.
|
|
123
630
|
|
|
124
|
-
*
|
|
631
|
+
*Hans Schnedlitz*
|
|
125
632
|
|
|
126
|
-
*
|
|
633
|
+
* Restore previous instrumenter after `execute_or_skip`
|
|
127
634
|
|
|
128
|
-
|
|
635
|
+
`FutureResult#execute_or_skip` replaces the thread's instrumenter with an
|
|
636
|
+
`EventBuffer` to collect events published during async query execution.
|
|
637
|
+
If the global async executor is saturated and the `caller_runs` fallback
|
|
638
|
+
executes the task on the calling thread, we need to make sure the previous
|
|
639
|
+
instrumenter is restored or the stale `EventBuffer` would stay in place and
|
|
640
|
+
permanently swallow all subsequent `sql.active_record` notifications on
|
|
641
|
+
that thread.
|
|
129
642
|
|
|
130
|
-
*
|
|
131
|
-
the same child association but different parents does not join all parents.
|
|
643
|
+
*Rosa Gutierrez*
|
|
132
644
|
|
|
133
|
-
|
|
645
|
+
* Bump the minimum PostgreSQL version to 9.5, due to usage of `array_position` function.
|
|
134
646
|
|
|
135
|
-
|
|
647
|
+
*Ivan Kuchin*
|
|
136
648
|
|
|
137
|
-
|
|
649
|
+
* Fix Ruby 4.0 delegator warning when calling inspect on ActiveRecord::Type::Serialized.
|
|
138
650
|
|
|
139
|
-
*
|
|
651
|
+
*Hammad Khan*
|
|
140
652
|
|
|
141
|
-
*
|
|
653
|
+
* Fix support for table names containing hyphens.
|
|
142
654
|
|
|
143
|
-
|
|
144
|
-
and DECIMAL. Consider using a simple CHECK constraint instead for such columns.
|
|
655
|
+
*Evgeniy Demin*
|
|
145
656
|
|
|
146
|
-
|
|
657
|
+
* Fix column deduplication for SQLite3 and PostgreSQL virtual (generated) columns.
|
|
147
658
|
|
|
148
|
-
|
|
659
|
+
`Column#==` and `Column#hash` now account for `virtual?` so that the
|
|
660
|
+
`Deduplicable` registry does not treat a generated column and a regular
|
|
661
|
+
column with the same name and type as identical. Previously, if a
|
|
662
|
+
generated column was registered first, a regular column on a different
|
|
663
|
+
table could be deduplicated to the generated instance, silently
|
|
664
|
+
excluding it from INSERT/UPDATE statements.
|
|
149
665
|
|
|
150
|
-
*
|
|
666
|
+
*Jay Huber*
|
|
151
667
|
|
|
152
|
-
|
|
153
|
-
which we have supported in the core. Now we support MySQL 5.6.4 or later, which
|
|
154
|
-
is the first version to support datetime with precision.
|
|
668
|
+
* Fix PostgreSQL schema dumping to handle schema-qualified table names in foreign_key references that span different schemas.
|
|
155
669
|
|
|
156
|
-
|
|
670
|
+
# before
|
|
671
|
+
add_foreign_key "hst.event_log_attributes", "hst.event_logs" # emits correctly because they're in the same schema (hst)
|
|
672
|
+
add_foreign_key "hst.event_log_attributes", "hst.usr.user_profiles", column: "created_by_id" # emits hst.user.* when user.* is expected
|
|
673
|
+
|
|
674
|
+
# after
|
|
675
|
+
add_foreign_key "hst.event_log_attributes", "hst.event_logs"
|
|
676
|
+
add_foreign_key "hst.event_log_attributes", "usr.user_profiles", column: "created_by_id"
|
|
677
|
+
|
|
678
|
+
*Chiperific*
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
## Rails 8.1.2.1 (March 23, 2026) ##
|
|
682
|
+
|
|
683
|
+
* No changes.
|
|
684
|
+
|
|
685
|
+
|
|
686
|
+
## Rails 8.1.2 (January 08, 2026) ##
|
|
687
|
+
|
|
688
|
+
* Fix counting cached queries in `ActiveRecord::RuntimeRegistry`.
|
|
157
689
|
|
|
158
|
-
*
|
|
690
|
+
*fatkodima*
|
|
691
|
+
|
|
692
|
+
* Fix merging relations with arel equality predicates with null relations.
|
|
693
|
+
|
|
694
|
+
*fatkodima*
|
|
695
|
+
|
|
696
|
+
* Fix SQLite3 schema dump for non-autoincrement integer primary keys.
|
|
697
|
+
|
|
698
|
+
Previously, `schema.rb` should incorrectly restore that table with an auto incrementing
|
|
699
|
+
primary key.
|
|
700
|
+
|
|
701
|
+
*Chris Hasiński*
|
|
702
|
+
|
|
703
|
+
* Fix PostgreSQL `schema_search_path` not being reapplied after `reset!` or `reconnect!`.
|
|
704
|
+
|
|
705
|
+
The `schema_search_path` configured in `database.yml` is now correctly
|
|
706
|
+
reapplied instead of falling back to PostgreSQL defaults.
|
|
707
|
+
|
|
708
|
+
*Tobias Egli*
|
|
709
|
+
|
|
710
|
+
* Restore the ability of enum to be foats.
|
|
711
|
+
|
|
712
|
+
```ruby
|
|
713
|
+
enum :rating, { low: 0.0, medium: 0.5, high: 1.0 },
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
In Rails 8.1.0, enum values are eagerly validated, and floats weren't expected.
|
|
717
|
+
|
|
718
|
+
*Said Kaldybaev*
|
|
159
719
|
|
|
160
|
-
|
|
161
|
-
fixtures impose all queries use the same connection.
|
|
720
|
+
* Ensure batched preloaded associations accounts for klass when grouping to avoid issues with STI.
|
|
162
721
|
|
|
163
|
-
|
|
164
|
-
|
|
722
|
+
*zzak*, *Stjepan Hadjic*
|
|
723
|
+
|
|
724
|
+
* Fix `ActiveRecord::SoleRecordExceeded#record` to return the relation.
|
|
725
|
+
|
|
726
|
+
This was the case until Rails 7.2, but starting from 8.0 it
|
|
727
|
+
started mistakenly returning the model class.
|
|
728
|
+
|
|
729
|
+
*Jean Boussier*
|
|
730
|
+
|
|
731
|
+
* Improve PostgreSQLAdapter resilience to Timeout.timeout.
|
|
732
|
+
|
|
733
|
+
Better handle asynchronous exceptions being thrown inside
|
|
734
|
+
the `reconnect!` method.
|
|
735
|
+
|
|
736
|
+
This may fixes some deep errors such as:
|
|
737
|
+
|
|
738
|
+
```
|
|
739
|
+
undefined method `key?' for nil:NilClass (NoMethodError)
|
|
740
|
+
if !type_map.key?(oid)
|
|
741
|
+
```
|
|
165
742
|
|
|
166
743
|
*Jean Boussier*
|
|
167
744
|
|
|
168
|
-
*
|
|
745
|
+
* Fix structured events for Active Record was not being emitted.
|
|
746
|
+
|
|
747
|
+
*Yuji Yaginuma*
|
|
748
|
+
|
|
749
|
+
* Fix `eager_load` when loading `has_many` assocations with composite primary keys.
|
|
169
750
|
|
|
170
|
-
This
|
|
751
|
+
This would result in some records being loaded multiple times.
|
|
171
752
|
|
|
172
|
-
*
|
|
753
|
+
*Martin-Alexander*
|
|
173
754
|
|
|
174
|
-
* Ensure `ActiveRecord::Encryption.config` is always ready before access.
|
|
175
755
|
|
|
176
|
-
|
|
177
|
-
was loaded. Therefore, accessing `ActiveRecord::Encryption.config` properties before
|
|
178
|
-
`ActiveRecord::Base` was loaded would give incorrect results.
|
|
756
|
+
## Rails 8.1.1 (October 28, 2025) ##
|
|
179
757
|
|
|
180
|
-
|
|
181
|
-
soon as needed.
|
|
758
|
+
* No changes.
|
|
182
759
|
|
|
183
|
-
When `ActiveRecord::Base` is loaded, even lazily, it in turn triggers the loading of
|
|
184
|
-
`ActiveRecord::Encryption`, thus preserving the original behavior of having its config ready
|
|
185
|
-
before any use of `ActiveRecord::Base`.
|
|
186
760
|
|
|
187
|
-
|
|
761
|
+
## Rails 8.1.0 (October 22, 2025) ##
|
|
188
762
|
|
|
189
|
-
*
|
|
190
|
-
their type, scale, limit & precision.
|
|
763
|
+
* Fix SQLite3 data loss during table alterations with CASCADE foreign keys.
|
|
191
764
|
|
|
192
|
-
|
|
765
|
+
When altering a table in SQLite3 that is referenced by child tables with
|
|
766
|
+
`ON DELETE CASCADE` foreign keys, ActiveRecord would silently delete all
|
|
767
|
+
data from the child tables. This occurred because SQLite requires table
|
|
768
|
+
recreation for schema changes, and during this process the original table
|
|
769
|
+
is temporarily dropped, triggering CASCADE deletes on child tables.
|
|
770
|
+
|
|
771
|
+
The root cause was incorrect ordering of operations. The original code
|
|
772
|
+
wrapped `disable_referential_integrity` inside a transaction, but
|
|
773
|
+
`PRAGMA foreign_keys` cannot be modified inside a transaction in SQLite -
|
|
774
|
+
attempting to do so simply has no effect. This meant foreign keys remained
|
|
775
|
+
enabled during table recreation, causing CASCADE deletes to fire.
|
|
776
|
+
|
|
777
|
+
The fix reverses the order to follow the official SQLite 12-step ALTER TABLE
|
|
778
|
+
procedure: `disable_referential_integrity` now wraps the transaction instead
|
|
779
|
+
of being wrapped by it. This ensures foreign keys are properly disabled
|
|
780
|
+
before the transaction starts and re-enabled after it commits, preventing
|
|
781
|
+
CASCADE deletes while maintaining data integrity through atomic transactions.
|
|
193
782
|
|
|
194
783
|
*Ruy Rocha*
|
|
195
784
|
|
|
196
|
-
* Add
|
|
785
|
+
* Add replicas to test database parallelization setup.
|
|
197
786
|
|
|
198
|
-
|
|
787
|
+
Setup and configuration of databases for parallel testing now includes replicas.
|
|
199
788
|
|
|
200
|
-
|
|
789
|
+
This fixes an issue when using a replica database, database selector middleware,
|
|
790
|
+
and non-transactional tests, where integration tests running in parallel would select
|
|
791
|
+
the base test database, i.e. `db_test`, instead of the numbered parallel worker database,
|
|
792
|
+
i.e. `db_test_{n}`.
|
|
201
793
|
|
|
202
|
-
*
|
|
794
|
+
*Adam Maas*
|
|
203
795
|
|
|
204
|
-
* Support
|
|
796
|
+
* Support virtual (not persisted) generated columns on PostgreSQL 18+
|
|
797
|
+
|
|
798
|
+
PostgreSQL 18 introduces virtual (not persisted) generated columns,
|
|
799
|
+
which are now the default unless the `stored: true` option is explicitly specified on PostgreSQL 18+.
|
|
205
800
|
|
|
206
801
|
```ruby
|
|
207
|
-
|
|
208
|
-
|
|
802
|
+
create_table :users do |t|
|
|
803
|
+
t.string :name
|
|
804
|
+
t.virtual :lower_name, type: :string, as: "LOWER(name)", stored: false
|
|
805
|
+
t.virtual :name_length, type: :integer, as: "LENGTH(name)"
|
|
209
806
|
end
|
|
210
807
|
```
|
|
211
808
|
|
|
212
|
-
*
|
|
809
|
+
*Yasuo Honda*
|
|
213
810
|
|
|
214
|
-
*
|
|
811
|
+
* Optimize schema dumping to prevent duplicate file generation.
|
|
215
812
|
|
|
216
|
-
|
|
813
|
+
`ActiveRecord::Tasks::DatabaseTasks.dump_all` now tracks which schema files
|
|
814
|
+
have already been dumped and skips dumping the same file multiple times.
|
|
815
|
+
This improves performance when multiple database configurations share the
|
|
816
|
+
same schema dump path.
|
|
217
817
|
|
|
218
|
-
*
|
|
818
|
+
*Mikey Gough*, *Hartley McGuire*
|
|
219
819
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
supported.
|
|
820
|
+
* Add structured events for Active Record:
|
|
821
|
+
- `active_record.strict_loading_violation`
|
|
822
|
+
- `active_record.sql`
|
|
224
823
|
|
|
824
|
+
*Gannon McGibbon*
|
|
825
|
+
|
|
826
|
+
* Add support for integer shard keys.
|
|
225
827
|
```ruby
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
828
|
+
# Now accepts symbols as shard keys.
|
|
829
|
+
ActiveRecord::Base.connects_to(shards: {
|
|
830
|
+
1: { writing: :primary_shard_one, reading: :primary_shard_one },
|
|
831
|
+
2: { writing: :primary_shard_two, reading: :primary_shard_two},
|
|
832
|
+
})
|
|
833
|
+
|
|
834
|
+
ActiveRecord::Base.connected_to(shard: 1) do
|
|
835
|
+
# ..
|
|
230
836
|
end
|
|
837
|
+
```
|
|
231
838
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
839
|
+
*Nony Dutton*
|
|
840
|
+
|
|
841
|
+
* Add `ActiveRecord::Base.only_columns`
|
|
842
|
+
|
|
843
|
+
Similar in use case to `ignored_columns` but listing columns to consider rather than the ones
|
|
844
|
+
to ignore.
|
|
845
|
+
|
|
846
|
+
Can be useful when working with a legacy or shared database schema, or to make safe schema change
|
|
847
|
+
in two deploys rather than three.
|
|
848
|
+
|
|
849
|
+
*Anton Kandratski*
|
|
850
|
+
|
|
851
|
+
* Use `PG::Connection#close_prepared` (protocol level Close) to deallocate
|
|
852
|
+
prepared statements when available.
|
|
853
|
+
|
|
854
|
+
To enable its use, you must have pg >= 1.6.0, libpq >= 17, and a PostgreSQL
|
|
855
|
+
database version >= 17.
|
|
856
|
+
|
|
857
|
+
*Hartley McGuire*, *Andrew Jackson*
|
|
858
|
+
|
|
859
|
+
* Fix query cache for pinned connections in multi threaded transactional tests
|
|
860
|
+
|
|
861
|
+
When a pinned connection is used across separate threads, they now use a separate cache store
|
|
862
|
+
for each thread.
|
|
863
|
+
|
|
864
|
+
This improve accuracy of system tests, and any test using multiple threads.
|
|
865
|
+
|
|
866
|
+
*Heinrich Lee Yu*, *Jean Boussier*
|
|
867
|
+
|
|
868
|
+
* Fix time attribute dirty tracking with timezone conversions.
|
|
869
|
+
|
|
870
|
+
Time-only attributes now maintain a fixed date of 2000-01-01 during timezone conversions,
|
|
871
|
+
preventing them from being incorrectly marked as changed due to date shifts.
|
|
872
|
+
|
|
873
|
+
This fixes an issue where time attributes would be marked as changed when setting the same time value
|
|
874
|
+
due to timezone conversion causing internal date shifts.
|
|
875
|
+
|
|
876
|
+
*Prateek Choudhary*
|
|
877
|
+
|
|
878
|
+
* Skip calling `PG::Connection#cancel` in `cancel_any_running_query`
|
|
879
|
+
when using libpq >= 18 with pg < 1.6.0, due to incompatibility.
|
|
880
|
+
Rollback still runs, but may take longer.
|
|
881
|
+
|
|
882
|
+
*Yasuo Honda*, *Lars Kanis*
|
|
883
|
+
|
|
884
|
+
* Don't add `id_value` attribute alias when attribute/column with that name already exists.
|
|
885
|
+
|
|
886
|
+
*Rob Lewis*
|
|
887
|
+
|
|
888
|
+
* Remove deprecated `:unsigned_float` and `:unsigned_decimal` column methods for MySQL.
|
|
889
|
+
|
|
890
|
+
*Rafael Mendonça França*
|
|
891
|
+
|
|
892
|
+
* Remove deprecated `:retries` option for the SQLite3 adapter.
|
|
893
|
+
|
|
894
|
+
*Rafael Mendonça França*
|
|
895
|
+
|
|
896
|
+
* Introduce new database configuration options `keepalive`, `max_age`, and
|
|
897
|
+
`min_connections` -- and rename `pool` to `max_connections` to match.
|
|
898
|
+
|
|
899
|
+
There are no changes to default behavior, but these allow for more specific
|
|
900
|
+
control over pool behavior.
|
|
901
|
+
|
|
902
|
+
*Matthew Draper*, *Chris AtLee*, *Rachael Wright-Munn*
|
|
903
|
+
|
|
904
|
+
* Move `LIMIT` validation from query generation to when `limit()` is called.
|
|
905
|
+
|
|
906
|
+
*Hartley McGuire*, *Shuyang*
|
|
907
|
+
|
|
908
|
+
* Add `ActiveRecord::CheckViolation` error class for check constraint violations.
|
|
909
|
+
|
|
910
|
+
*Ryuta Kamizono*
|
|
911
|
+
|
|
912
|
+
* Add `ActiveRecord::ExclusionViolation` error class for exclusion constraint violations.
|
|
913
|
+
|
|
914
|
+
When an exclusion constraint is violated in PostgreSQL, the error will now be raised
|
|
915
|
+
as `ActiveRecord::ExclusionViolation` instead of the generic `ActiveRecord::StatementInvalid`,
|
|
916
|
+
making it easier to handle these specific constraint violations in application code.
|
|
917
|
+
|
|
918
|
+
This follows the same pattern as other constraint violation error classes like
|
|
919
|
+
`RecordNotUnique` for unique constraint violations and `InvalidForeignKey` for
|
|
920
|
+
foreign key constraint violations.
|
|
921
|
+
|
|
922
|
+
*Ryuta Kamizono*
|
|
923
|
+
|
|
924
|
+
* Attributes filtered by `filter_attributes` will now also be filtered by `filter_parameters`
|
|
925
|
+
so sensitive information is not leaked.
|
|
926
|
+
|
|
927
|
+
*Jill Klang*
|
|
928
|
+
|
|
929
|
+
* Add `connection.current_transaction.isolation` API to check current transaction's isolation level.
|
|
930
|
+
|
|
931
|
+
Returns the isolation level if it was explicitly set via the `isolation:` parameter
|
|
932
|
+
or through `ActiveRecord.with_transaction_isolation_level`, otherwise returns `nil`.
|
|
933
|
+
Nested transactions return the parent transaction's isolation level.
|
|
934
|
+
|
|
935
|
+
```ruby
|
|
936
|
+
# Returns nil when no transaction
|
|
937
|
+
User.connection.current_transaction.isolation # => nil
|
|
938
|
+
|
|
939
|
+
# Returns explicitly set isolation level
|
|
940
|
+
User.transaction(isolation: :serializable) do
|
|
941
|
+
User.connection.current_transaction.isolation # => :serializable
|
|
942
|
+
end
|
|
943
|
+
|
|
944
|
+
# Returns nil when isolation not explicitly set
|
|
945
|
+
User.transaction do
|
|
946
|
+
User.connection.current_transaction.isolation # => nil
|
|
947
|
+
end
|
|
948
|
+
|
|
949
|
+
# Nested transactions inherit parent's isolation
|
|
950
|
+
User.transaction(isolation: :read_committed) do
|
|
951
|
+
User.transaction do
|
|
952
|
+
User.connection.current_transaction.isolation # => :read_committed
|
|
953
|
+
end
|
|
954
|
+
end
|
|
238
955
|
```
|
|
239
956
|
|
|
240
|
-
*
|
|
957
|
+
*Kir Shatrov*
|
|
241
958
|
|
|
242
|
-
*
|
|
959
|
+
* Fix `#merge` with `#or` or `#and` and a mixture of attributes and SQL strings resulting in an incorrect query.
|
|
243
960
|
|
|
244
|
-
|
|
961
|
+
```ruby
|
|
962
|
+
base = Comment.joins(:post).where(user_id: 1).where("recent = 1")
|
|
963
|
+
puts base.merge(base.where(draft: true).or(Post.where(archived: true))).to_sql
|
|
964
|
+
```
|
|
245
965
|
|
|
246
|
-
|
|
966
|
+
Before:
|
|
967
|
+
|
|
968
|
+
```SQL
|
|
969
|
+
SELECT "comments".* FROM "comments"
|
|
970
|
+
INNER JOIN "posts" ON "posts"."id" = "comments"."post_id"
|
|
971
|
+
WHERE (recent = 1)
|
|
972
|
+
AND (
|
|
973
|
+
"comments"."user_id" = 1
|
|
974
|
+
AND (recent = 1)
|
|
975
|
+
AND "comments"."draft" = 1
|
|
976
|
+
OR "posts"."archived" = 1
|
|
977
|
+
)
|
|
978
|
+
```
|
|
247
979
|
|
|
248
|
-
|
|
980
|
+
After:
|
|
981
|
+
|
|
982
|
+
```SQL
|
|
983
|
+
SELECT "comments".* FROM "comments"
|
|
984
|
+
INNER JOIN "posts" ON "posts"."id" = "comments"."post_id"
|
|
985
|
+
WHERE "comments"."user_id" = 1
|
|
986
|
+
AND (recent = 1)
|
|
987
|
+
AND (
|
|
988
|
+
"comments"."user_id" = 1
|
|
989
|
+
AND (recent = 1)
|
|
990
|
+
AND "comments"."draft" = 1
|
|
991
|
+
OR "posts"."archived" = 1
|
|
992
|
+
)
|
|
993
|
+
```
|
|
249
994
|
|
|
250
|
-
*
|
|
995
|
+
*Joshua Young*
|
|
251
996
|
|
|
252
|
-
*
|
|
997
|
+
* Make schema dumper to account for `ActiveRecord.dump_schemas` when dumping in `:ruby` format.
|
|
253
998
|
|
|
254
|
-
|
|
255
|
-
`enable_extension` statements if they differ from the current schema.
|
|
999
|
+
*fatkodima*
|
|
256
1000
|
|
|
257
|
-
|
|
1001
|
+
* Add `:touch` option to `update_column`/`update_columns` methods.
|
|
258
1002
|
|
|
259
1003
|
```ruby
|
|
260
|
-
|
|
261
|
-
|
|
1004
|
+
# Will update :updated_at/:updated_on alongside :nice column.
|
|
1005
|
+
user.update_column(:nice, true, touch: true)
|
|
1006
|
+
|
|
1007
|
+
# Will update :updated_at/:updated_on alongside :last_ip column
|
|
1008
|
+
user.update_columns(last_ip: request.remote_ip, touch: true)
|
|
262
1009
|
```
|
|
263
1010
|
|
|
264
|
-
|
|
1011
|
+
*Dmitrii Ivliev*
|
|
1012
|
+
|
|
1013
|
+
* Optimize Active Record batching further when using ranges.
|
|
1014
|
+
|
|
1015
|
+
Tested on a PostgreSQL table with 10M records and batches of 10k records, the generation
|
|
1016
|
+
of relations for the 1000 batches was `4.8x` faster (`6.8s` vs. `1.4s`), used `900x`
|
|
1017
|
+
less bandwidth (`180MB` vs. `0.2MB`) and allocated `45x` less memory (`490MB` vs. `11MB`).
|
|
1018
|
+
|
|
1019
|
+
*Maxime Réty*, *fatkodima*
|
|
1020
|
+
|
|
1021
|
+
* Include current character length in error messages for index and table name length validations.
|
|
1022
|
+
|
|
1023
|
+
*Joshua Young*
|
|
1024
|
+
|
|
1025
|
+
* Add `rename_schema` method for PostgreSQL.
|
|
1026
|
+
|
|
1027
|
+
*T S Vallender*
|
|
1028
|
+
|
|
1029
|
+
* Implement support for deprecating associations:
|
|
265
1030
|
|
|
266
1031
|
```ruby
|
|
267
|
-
|
|
268
|
-
enable_extension "pg_stat_statements"
|
|
1032
|
+
has_many :posts, deprecated: true
|
|
269
1033
|
```
|
|
270
1034
|
|
|
271
|
-
|
|
1035
|
+
With that, Active Record will report any usage of the `posts` association.
|
|
272
1036
|
|
|
273
|
-
|
|
274
|
-
|
|
1037
|
+
Three reporting modes are supported (`:warn`, `:raise`, and `:notify`), and
|
|
1038
|
+
backtraces can be enabled or disabled. Defaults are `:warn` mode and
|
|
1039
|
+
disabled backtraces.
|
|
275
1040
|
|
|
276
|
-
|
|
1041
|
+
Please, check the docs for further details.
|
|
1042
|
+
|
|
1043
|
+
*Xavier Noria*
|
|
277
1044
|
|
|
278
|
-
*
|
|
1045
|
+
* PostgreSQL adapter create DB now supports `locale_provider` and `locale`.
|
|
279
1046
|
|
|
280
|
-
|
|
281
|
-
aggregated in a single bulk insert command.
|
|
1047
|
+
*Bengt-Ove Hollaender*
|
|
282
1048
|
|
|
283
|
-
|
|
1049
|
+
* Use ntuples to populate row_count instead of count for Postgres
|
|
284
1050
|
|
|
285
|
-
*
|
|
1051
|
+
*Jonathan Calvert*
|
|
286
1052
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
actually take a schema name (unlike `CREATE EXTENSION`), so the resulting SQL statement will only name
|
|
290
|
-
the extension, e.g. `DROP EXTENSION IF EXISTS "pgcrypto"`.
|
|
1053
|
+
* Fix checking whether an unpersisted record is `include?`d in a strictly
|
|
1054
|
+
loaded `has_and_belongs_to_many` association.
|
|
291
1055
|
|
|
292
|
-
*
|
|
1056
|
+
*Hartley McGuire*
|
|
293
1057
|
|
|
294
|
-
*
|
|
1058
|
+
* Add ability to change transaction isolation for all pools within a block.
|
|
295
1059
|
|
|
296
|
-
|
|
1060
|
+
This functionality is useful if your application needs to change the database
|
|
1061
|
+
transaction isolation for a request or action.
|
|
297
1062
|
|
|
298
|
-
|
|
1063
|
+
Calling `ActiveRecord.with_transaction_isolation_level(level) {}` in an around filter or
|
|
1064
|
+
middleware will set the transaction isolation for all pools accessed within the block,
|
|
1065
|
+
but not for the pools that aren't.
|
|
299
1066
|
|
|
300
|
-
|
|
1067
|
+
This works with explicit and implicit transactions:
|
|
301
1068
|
|
|
302
1069
|
```ruby
|
|
303
|
-
|
|
304
|
-
|
|
1070
|
+
ActiveRecord.with_transaction_isolation_level(:read_committed) do
|
|
1071
|
+
Tag.transaction do # opens a transaction explicitly
|
|
1072
|
+
Tag.create!
|
|
1073
|
+
end
|
|
305
1074
|
end
|
|
306
1075
|
```
|
|
307
1076
|
|
|
308
|
-
|
|
1077
|
+
```ruby
|
|
1078
|
+
ActiveRecord.with_transaction_isolation_level(:read_committed) do
|
|
1079
|
+
Tag.create! # opens a transaction implicitly
|
|
1080
|
+
end
|
|
1081
|
+
```
|
|
1082
|
+
|
|
1083
|
+
*Eileen M. Uchitelle*
|
|
309
1084
|
|
|
310
|
-
*
|
|
1085
|
+
* Raise `ActiveRecord::MissingRequiredOrderError` when order dependent finder methods (e.g. `#first`, `#last`) are
|
|
1086
|
+
called without `order` values on the relation, and the model does not have any order columns (`implicit_order_column`,
|
|
1087
|
+
`query_constraints`, or `primary_key`) to fall back on.
|
|
311
1088
|
|
|
312
|
-
|
|
1089
|
+
This change will be introduced with a new framework default for Rails 8.1, and the current behavior of not raising
|
|
1090
|
+
an error has been deprecated with the aim of removing the configuration option in Rails 8.2.
|
|
313
1091
|
|
|
314
|
-
|
|
1092
|
+
```ruby
|
|
1093
|
+
config.active_record.raise_on_missing_required_finder_order_columns = true
|
|
1094
|
+
```
|
|
315
1095
|
|
|
316
|
-
*
|
|
1096
|
+
*Joshua Young*
|
|
317
1097
|
|
|
318
|
-
|
|
1098
|
+
* `:class_name` is now invalid in polymorphic `belongs_to` associations.
|
|
319
1099
|
|
|
320
|
-
|
|
1100
|
+
Reason is `:class_name` does not make sense in those associations because
|
|
1101
|
+
the class name of target records is dynamic and stored in the type column.
|
|
321
1102
|
|
|
322
|
-
|
|
1103
|
+
Existing polymorphic associations setting this option can just delete it.
|
|
1104
|
+
While it did not raise, it had no effect anyway.
|
|
323
1105
|
|
|
324
1106
|
*Xavier Noria*
|
|
325
1107
|
|
|
326
|
-
*
|
|
1108
|
+
* Add support for multiple databases to `db:migrate:reset`.
|
|
327
1109
|
|
|
328
|
-
|
|
329
|
-
`after_validation`, `before_save` and `after_save` callbacks twice.
|
|
1110
|
+
*Joé Dupuis*
|
|
330
1111
|
|
|
331
|
-
|
|
1112
|
+
* Add `affected_rows` to `ActiveRecord::Result`.
|
|
332
1113
|
|
|
333
|
-
*
|
|
1114
|
+
*Jenny Shen*
|
|
334
1115
|
|
|
335
|
-
*
|
|
1116
|
+
* Enable passing retryable SqlLiterals to `#where`.
|
|
336
1117
|
|
|
337
|
-
|
|
338
|
-
module ZstdCompressor
|
|
339
|
-
def self.deflate(data)
|
|
340
|
-
Zstd.compress(data)
|
|
341
|
-
end
|
|
1118
|
+
*Hartley McGuire*
|
|
342
1119
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
1120
|
+
* Set default for primary keys in `insert_all`/`upsert_all`.
|
|
1121
|
+
|
|
1122
|
+
Previously in Postgres, updating and inserting new records in one upsert wasn't possible
|
|
1123
|
+
due to null primary key values. `nil` primary key values passed into `insert_all`/`upsert_all`
|
|
1124
|
+
are now implicitly set to the default insert value specified by adapter.
|
|
1125
|
+
|
|
1126
|
+
*Jenny Shen*
|
|
1127
|
+
|
|
1128
|
+
* Add a load hook `active_record_database_configurations` for `ActiveRecord::DatabaseConfigurations`
|
|
1129
|
+
|
|
1130
|
+
*Mike Dalessio*
|
|
1131
|
+
|
|
1132
|
+
* Use `TRUE` and `FALSE` for SQLite queries with boolean columns.
|
|
1133
|
+
|
|
1134
|
+
*Hartley McGuire*
|
|
1135
|
+
|
|
1136
|
+
* Bump minimum supported SQLite to 3.23.0.
|
|
1137
|
+
|
|
1138
|
+
*Hartley McGuire*
|
|
1139
|
+
|
|
1140
|
+
* Allow allocated Active Records to lookup associations.
|
|
1141
|
+
|
|
1142
|
+
Previously, the association cache isn't setup on allocated record objects, so association
|
|
1143
|
+
lookups will crash. Test frameworks like mocha use allocate to check for stubbable instance
|
|
1144
|
+
methods, which can trigger an association lookup.
|
|
1145
|
+
|
|
1146
|
+
*Gannon McGibbon*
|
|
1147
|
+
|
|
1148
|
+
* Encryption now supports `support_unencrypted_data: true` being set per-attribute.
|
|
1149
|
+
|
|
1150
|
+
Previously this only worked if `ActiveRecord::Encryption.config.support_unencrypted_data == true`.
|
|
1151
|
+
Now, if the global config is turned off, you can still opt in for a specific attribute.
|
|
1152
|
+
|
|
1153
|
+
```ruby
|
|
1154
|
+
# ActiveRecord::Encryption.config.support_unencrypted_data = true
|
|
1155
|
+
class User < ActiveRecord::Base
|
|
1156
|
+
encrypts :name, support_unencrypted_data: false # only supports encrypted data
|
|
1157
|
+
encrypts :email # supports encrypted or unencrypted data
|
|
346
1158
|
end
|
|
1159
|
+
```
|
|
347
1160
|
|
|
348
|
-
|
|
349
|
-
|
|
1161
|
+
```ruby
|
|
1162
|
+
# ActiveRecord::Encryption.config.support_unencrypted_data = false
|
|
1163
|
+
class User < ActiveRecord::Base
|
|
1164
|
+
encrypts :name, support_unencrypted_data: true # supports encrypted or unencrypted data
|
|
1165
|
+
encrypts :email # only supports encrypted data
|
|
350
1166
|
end
|
|
351
1167
|
```
|
|
352
1168
|
|
|
353
|
-
|
|
1169
|
+
*Alex Ghiculescu*
|
|
1170
|
+
|
|
1171
|
+
* Model generator no longer needs a database connection to validate column types.
|
|
1172
|
+
|
|
1173
|
+
*Mike Dalessio*
|
|
1174
|
+
|
|
1175
|
+
* Allow signed ID verifiers to be configurable via `Rails.application.message_verifiers`
|
|
1176
|
+
|
|
1177
|
+
Prior to this change, the primary way to configure signed ID verifiers was
|
|
1178
|
+
to set `signed_id_verifier` on each model class:
|
|
1179
|
+
|
|
1180
|
+
```ruby
|
|
1181
|
+
Post.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
|
|
1182
|
+
Comment.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
|
|
1183
|
+
```
|
|
1184
|
+
|
|
1185
|
+
And if the developer did not set `signed_id_verifier`, a verifier would be
|
|
1186
|
+
instantiated with a secret derived from `secret_key_base` and the following
|
|
1187
|
+
options:
|
|
1188
|
+
|
|
1189
|
+
```ruby
|
|
1190
|
+
{ digest: "SHA256", serializer: JSON, url_safe: true }
|
|
1191
|
+
```
|
|
1192
|
+
|
|
1193
|
+
Thus it was cumbersome to rotate configuration for all verifiers.
|
|
1194
|
+
|
|
1195
|
+
This change defines a new Rails config: [`config.active_record.use_legacy_signed_id_verifier`][].
|
|
1196
|
+
The default value is `:generate_and_verify`, which preserves the previous
|
|
1197
|
+
behavior. However, when set to `:verify`, signed ID verifiers will use
|
|
1198
|
+
configuration from `Rails.application.message_verifiers` (specifically,
|
|
1199
|
+
`Rails.application.message_verifiers["active_record/signed_id"]`) to
|
|
1200
|
+
generate and verify signed IDs, but will also verify signed IDs using the
|
|
1201
|
+
older configuration.
|
|
1202
|
+
|
|
1203
|
+
To avoid complication, the new behavior only applies when `signed_id_verifier_secret`
|
|
1204
|
+
is not set on a model class or any of its ancestors. Additionally,
|
|
1205
|
+
`signed_id_verifier_secret` is now deprecated. If you are currently setting
|
|
1206
|
+
`signed_id_verifier_secret` on a model class, you can set `signed_id_verifier`
|
|
1207
|
+
instead:
|
|
1208
|
+
|
|
1209
|
+
```ruby
|
|
1210
|
+
# BEFORE
|
|
1211
|
+
Post.signed_id_verifier_secret = "my secret"
|
|
1212
|
+
|
|
1213
|
+
# AFTER
|
|
1214
|
+
Post.signed_id_verifier = ActiveSupport::MessageVerifier.new("my secret", digest: "SHA256", serializer: JSON, url_safe: true)
|
|
1215
|
+
```
|
|
1216
|
+
|
|
1217
|
+
To ease migration, `signed_id_verifier` has also been changed to behave as a
|
|
1218
|
+
`class_attribute` (i.e. inheritable), but _only when `signed_id_verifier_secret`
|
|
1219
|
+
is not set_:
|
|
1220
|
+
|
|
1221
|
+
```ruby
|
|
1222
|
+
# BEFORE
|
|
1223
|
+
ActiveRecord::Base.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
|
|
1224
|
+
Post.signed_id_verifier == ActiveRecord::Base.signed_id_verifier # => false
|
|
1225
|
+
|
|
1226
|
+
# AFTER
|
|
1227
|
+
ActiveRecord::Base.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
|
|
1228
|
+
Post.signed_id_verifier == ActiveRecord::Base.signed_id_verifier # => true
|
|
1229
|
+
|
|
1230
|
+
Post.signed_id_verifier_secret = "my secret" # => deprecation warning
|
|
1231
|
+
Post.signed_id_verifier == ActiveRecord::Base.signed_id_verifier # => false
|
|
1232
|
+
```
|
|
1233
|
+
|
|
1234
|
+
Note, however, that it is recommended to eventually migrate from
|
|
1235
|
+
model-specific verifiers to a unified configuration managed by
|
|
1236
|
+
`Rails.application.message_verifiers`. `ActiveSupport::MessageVerifier#rotate`
|
|
1237
|
+
can facilitate that transition. For example:
|
|
1238
|
+
|
|
1239
|
+
```ruby
|
|
1240
|
+
# BEFORE
|
|
1241
|
+
# Generate and verify signed Post IDs using Post-specific configuration
|
|
1242
|
+
Post.signed_id_verifier = ActiveSupport::MessageVerifier.new("post secret", ...)
|
|
1243
|
+
|
|
1244
|
+
# AFTER
|
|
1245
|
+
# Generate and verify signed Post IDs using the unified configuration
|
|
1246
|
+
Post.signed_id_verifier = Post.signed_id_verifier.dup
|
|
1247
|
+
# Fall back to Post-specific configuration when verifying signed IDs
|
|
1248
|
+
Post.signed_id_verifier.rotate("post secret", ...)
|
|
1249
|
+
```
|
|
1250
|
+
|
|
1251
|
+
[`config.active_record.use_legacy_signed_id_verifier`]: https://guides.rubyonrails.org/v8.1/configuring.html#config-active-record-use-legacy-signed-id-verifier
|
|
1252
|
+
|
|
1253
|
+
*Ali Sepehri*, *Jonathan Hefner*
|
|
1254
|
+
|
|
1255
|
+
* Prepend `extra_flags` in postgres' `structure_load`
|
|
1256
|
+
|
|
1257
|
+
When specifying `structure_load_flags` with a postgres adapter, the flags
|
|
1258
|
+
were appended to the default flags, instead of prepended.
|
|
1259
|
+
This caused issues with flags not being taken into account by postgres.
|
|
1260
|
+
|
|
1261
|
+
*Alice Loeser*
|
|
1262
|
+
|
|
1263
|
+
* Allow bypassing primary key/constraint addition in `implicit_order_column`
|
|
1264
|
+
|
|
1265
|
+
When specifying multiple columns in an array for `implicit_order_column`, adding
|
|
1266
|
+
`nil` as the last element will prevent appending the primary key to order
|
|
1267
|
+
conditions. This allows more precise control of indexes used by
|
|
1268
|
+
generated queries. It should be noted that this feature does introduce the risk
|
|
1269
|
+
of API misbehavior if the specified columns are not fully unique.
|
|
1270
|
+
|
|
1271
|
+
*Issy Long*
|
|
1272
|
+
|
|
1273
|
+
* Allow setting the `schema_format` via database configuration.
|
|
1274
|
+
|
|
1275
|
+
```
|
|
1276
|
+
primary:
|
|
1277
|
+
schema_format: ruby
|
|
1278
|
+
```
|
|
1279
|
+
|
|
1280
|
+
Useful for multi-database setups when apps require different formats per-database.
|
|
1281
|
+
|
|
1282
|
+
*T S Vallender*
|
|
1283
|
+
|
|
1284
|
+
* Support disabling indexes for MySQL v8.0.0+ and MariaDB v10.6.0+
|
|
1285
|
+
|
|
1286
|
+
MySQL 8.0.0 added an option to disable indexes from being used by the query
|
|
1287
|
+
optimizer by making them "invisible". This allows the index to still be maintained
|
|
1288
|
+
and updated but no queries will be permitted to use it. This can be useful for adding
|
|
1289
|
+
new invisible indexes or making existing indexes invisible before dropping them
|
|
1290
|
+
to ensure queries are not negatively affected.
|
|
1291
|
+
See https://dev.mysql.com/blog-archive/mysql-8-0-invisible-indexes/ for more details.
|
|
1292
|
+
|
|
1293
|
+
MariaDB 10.6.0 also added support for this feature by allowing indexes to be "ignored"
|
|
1294
|
+
in queries. See https://mariadb.com/kb/en/ignored-indexes/ for more details.
|
|
1295
|
+
|
|
1296
|
+
Active Record now supports this option for MySQL 8.0.0+ and MariaDB 10.6.0+ for
|
|
1297
|
+
index creation and alteration where the new index option `enabled: true/false` can be
|
|
1298
|
+
passed to column and index methods as below:
|
|
354
1299
|
|
|
355
1300
|
```ruby
|
|
356
|
-
|
|
357
|
-
|
|
1301
|
+
add_index :users, :email, enabled: false
|
|
1302
|
+
enable_index :users, :email
|
|
1303
|
+
add_column :users, :dob, :string, index: { enabled: false }
|
|
1304
|
+
|
|
1305
|
+
change_table :users do |t|
|
|
1306
|
+
t.index :name, enabled: false
|
|
1307
|
+
t.index :dob
|
|
1308
|
+
t.disable_index :dob
|
|
1309
|
+
t.column :username, :string, index: { enabled: false }
|
|
1310
|
+
t.references :account, index: { enabled: false }
|
|
1311
|
+
end
|
|
1312
|
+
|
|
1313
|
+
create_table :users do |t|
|
|
1314
|
+
t.string :name, index: { enabled: false }
|
|
1315
|
+
t.string :email
|
|
1316
|
+
t.index :email, enabled: false
|
|
358
1317
|
end
|
|
359
1318
|
```
|
|
360
1319
|
|
|
361
|
-
*
|
|
1320
|
+
*Merve Taner*
|
|
1321
|
+
|
|
1322
|
+
* Respect `implicit_order_column` in `ActiveRecord::Relation#reverse_order`.
|
|
1323
|
+
|
|
1324
|
+
*Joshua Young*
|
|
1325
|
+
|
|
1326
|
+
* Add column types to `ActiveRecord::Result` for SQLite3.
|
|
1327
|
+
|
|
1328
|
+
*Andrew Kane*
|
|
1329
|
+
|
|
1330
|
+
* Raise `ActiveRecord::ReadOnlyError` when pessimistically locking with a readonly role.
|
|
1331
|
+
|
|
1332
|
+
*Joshua Young*
|
|
1333
|
+
|
|
1334
|
+
* Fix using the `SQLite3Adapter`'s `dbconsole` method outside of a Rails application.
|
|
1335
|
+
|
|
1336
|
+
*Hartley McGuire*
|
|
1337
|
+
|
|
1338
|
+
* Fix migrating multiple databases with `ActiveRecord::PendingMigration` action.
|
|
1339
|
+
|
|
1340
|
+
*Gannon McGibbon*
|
|
1341
|
+
|
|
1342
|
+
* Enable automatically retrying idempotent association queries on connection
|
|
1343
|
+
errors.
|
|
1344
|
+
|
|
1345
|
+
*Hartley McGuire*
|
|
1346
|
+
|
|
1347
|
+
* Add `allow_retry` to `sql.active_record` instrumentation.
|
|
362
1348
|
|
|
363
|
-
|
|
364
|
-
`DatabaseConfig`.
|
|
1349
|
+
This enables identifying queries which queries are automatically retryable on connection errors.
|
|
365
1350
|
|
|
366
1351
|
*Hartley McGuire*
|
|
367
1352
|
|
|
368
|
-
*
|
|
1353
|
+
* Better support UPDATE with JOIN for Postgresql and SQLite3
|
|
1354
|
+
|
|
1355
|
+
Previously when generating update queries with one or more JOIN clauses,
|
|
1356
|
+
Active Record would use a sub query which would prevent to reference the joined
|
|
1357
|
+
tables in the `SET` clause, for instance:
|
|
369
1358
|
|
|
370
1359
|
```ruby
|
|
371
|
-
|
|
372
|
-
|
|
1360
|
+
Comment.joins(:post).update_all("title = posts.title")
|
|
1361
|
+
```
|
|
373
1362
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
1363
|
+
This is now supported as long as the relation doesn't also use a `LIMIT`, `ORDER` or
|
|
1364
|
+
`GROUP BY` clause. This was supported by the MySQL adapter for a long time.
|
|
1365
|
+
|
|
1366
|
+
*Jean Boussier*
|
|
1367
|
+
|
|
1368
|
+
* Introduce a before-fork hook in `ActiveSupport::Testing::Parallelization` to clear existing
|
|
1369
|
+
connections, to avoid fork-safety issues with the mysql2 adapter.
|
|
379
1370
|
|
|
380
|
-
|
|
1371
|
+
Fixes #41776
|
|
1372
|
+
|
|
1373
|
+
*Mike Dalessio*, *Donal McBreen*
|
|
1374
|
+
|
|
1375
|
+
* PoolConfig no longer keeps a reference to the connection class.
|
|
1376
|
+
|
|
1377
|
+
Keeping a reference to the class caused subtle issues when combined with reloading in
|
|
1378
|
+
development. Fixes #54343.
|
|
1379
|
+
|
|
1380
|
+
*Mike Dalessio*
|
|
1381
|
+
|
|
1382
|
+
* Fix SQL notifications sometimes not sent when using async queries.
|
|
1383
|
+
|
|
1384
|
+
```ruby
|
|
1385
|
+
Post.async_count
|
|
1386
|
+
ActiveSupport::Notifications.subscribed(->(*) { "Will never reach here" }) do
|
|
1387
|
+
Post.count
|
|
381
1388
|
end
|
|
1389
|
+
```
|
|
1390
|
+
|
|
1391
|
+
In rare circumstances and under the right race condition, Active Support notifications
|
|
1392
|
+
would no longer be dispatched after using an asynchronous query.
|
|
1393
|
+
This is now fixed.
|
|
1394
|
+
|
|
1395
|
+
*Edouard Chin*
|
|
1396
|
+
|
|
1397
|
+
* Eliminate queries loading dumped schema cache on Postgres
|
|
382
1398
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
1399
|
+
Improve resiliency by avoiding needing to open a database connection to load the
|
|
1400
|
+
type map while defining attribute methods at boot when a schema cache file is
|
|
1401
|
+
configured on PostgreSQL databases.
|
|
1402
|
+
|
|
1403
|
+
*James Coleman*
|
|
1404
|
+
|
|
1405
|
+
* `ActiveRecord::Coder::JSON` can be instantiated
|
|
1406
|
+
|
|
1407
|
+
Options can now be passed to `ActiveRecord::Coder::JSON` when instantiating the coder. This allows:
|
|
1408
|
+
```ruby
|
|
1409
|
+
serialize :config, coder: ActiveRecord::Coder::JSON.new(symbolize_names: true)
|
|
386
1410
|
```
|
|
1411
|
+
*matthaigh27*
|
|
387
1412
|
|
|
388
|
-
|
|
1413
|
+
* Deprecate using `insert_all`/`upsert_all` with unpersisted records in associations.
|
|
1414
|
+
|
|
1415
|
+
Using these methods on associations containing unpersisted records will now
|
|
1416
|
+
show a deprecation warning, as the unpersisted records will be lost after
|
|
1417
|
+
the operation.
|
|
389
1418
|
|
|
390
|
-
*
|
|
391
|
-
by these values.
|
|
1419
|
+
*Nick Schwaderer*
|
|
392
1420
|
|
|
393
|
-
|
|
1421
|
+
* Make column name optional for `index_exists?`.
|
|
394
1422
|
|
|
395
|
-
|
|
396
|
-
|
|
1423
|
+
This aligns well with `remove_index` signature as well, where
|
|
1424
|
+
index name doesn't need to be derived from the column names.
|
|
397
1425
|
|
|
398
|
-
*
|
|
1426
|
+
*Ali Ismayiliov*
|
|
399
1427
|
|
|
400
|
-
*
|
|
1428
|
+
* Change the payload name of `sql.active_record` notification for eager
|
|
1429
|
+
loading from "SQL" to "#{model.name} Eager Load".
|
|
401
1430
|
|
|
402
|
-
|
|
1431
|
+
*zzak*
|
|
403
1432
|
|
|
404
|
-
|
|
1433
|
+
* Enable automatically retrying idempotent `#exists?` queries on connection
|
|
1434
|
+
errors.
|
|
405
1435
|
|
|
406
|
-
*
|
|
1436
|
+
*Hartley McGuire*, *classidied*
|
|
407
1437
|
|
|
408
|
-
|
|
1438
|
+
* Deprecate usage of unsupported methods in conjunction with `update_all`:
|
|
409
1439
|
|
|
410
|
-
|
|
1440
|
+
`update_all` will now print a deprecation message if a query includes either `WITH`,
|
|
1441
|
+
`WITH RECURSIVE` or `DISTINCT` statements. Those were never supported and were ignored
|
|
1442
|
+
when generating the SQL query.
|
|
411
1443
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
`ActiveRecord.store`.
|
|
1444
|
+
An error will be raised in a future Rails release. This behavior will be consistent
|
|
1445
|
+
with `delete_all` which currently raises an error for unsupported statements.
|
|
415
1446
|
|
|
416
|
-
|
|
1447
|
+
*Edouard Chin*
|
|
417
1448
|
|
|
418
|
-
|
|
1449
|
+
* The table columns inside `schema.rb` are now sorted alphabetically.
|
|
419
1450
|
|
|
420
|
-
|
|
1451
|
+
Previously they'd be sorted by creation order, which can cause merge conflicts when two
|
|
1452
|
+
branches modify the same table concurrently.
|
|
421
1453
|
|
|
422
|
-
|
|
423
|
-
Please make sure the column is declared serializable via 'ActiveRecord.store' or, if your
|
|
424
|
-
database supports it, use a structured column type like hstore or json.
|
|
1454
|
+
*John Duff*
|
|
425
1455
|
|
|
426
|
-
|
|
1456
|
+
* Introduce versions formatter for the schema dumper.
|
|
1457
|
+
|
|
1458
|
+
It is now possible to override how schema dumper formats versions information inside the
|
|
1459
|
+
`structure.sql` file. Currently, the versions are simply sorted in the decreasing order.
|
|
1460
|
+
Within large teams, this can potentially cause many merge conflicts near the top of the list.
|
|
1461
|
+
|
|
1462
|
+
Now, the custom formatter can be provided with a custom sorting logic (e.g. by hash values
|
|
1463
|
+
of the versions), which can greatly reduce the number of conflicts.
|
|
1464
|
+
|
|
1465
|
+
*fatkodima*
|
|
427
1466
|
|
|
428
|
-
*
|
|
1467
|
+
* Serialized attributes can now be marked as comparable.
|
|
429
1468
|
|
|
430
|
-
|
|
1469
|
+
A not rare issue when working with serialized attributes is that the serialized representation of an object
|
|
1470
|
+
can change over time. Either because you are migrating from one serializer to the other (e.g. YAML to JSON or to msgpack),
|
|
1471
|
+
or because the serializer used subtly changed its output.
|
|
1472
|
+
|
|
1473
|
+
One example is libyaml that used to have some extra trailing whitespaces, and recently fixed that.
|
|
1474
|
+
When this sorts of thing happen, you end up with lots of records that report being changed even though
|
|
1475
|
+
they aren't, which in the best case leads to a lot more writes to the database and in the worst case lead to nasty bugs.
|
|
1476
|
+
|
|
1477
|
+
The solution is to instead compare the deserialized representation of the object, however Active Record
|
|
1478
|
+
can't assume the deserialized object has a working `==` method. Hence why this new functionality is opt-in.
|
|
431
1479
|
|
|
432
1480
|
```ruby
|
|
433
|
-
|
|
434
|
-
has_one :post, through: :other
|
|
435
|
-
end
|
|
1481
|
+
serialize :config, type: Hash, coder: JSON, comparable: true
|
|
436
1482
|
```
|
|
437
1483
|
|
|
438
|
-
|
|
1484
|
+
*Jean Boussier*
|
|
1485
|
+
|
|
1486
|
+
* Fix MySQL default functions getting dropped when changing a column's nullability.
|
|
439
1487
|
|
|
440
|
-
*
|
|
1488
|
+
*Bastian Bartmann*
|
|
1489
|
+
|
|
1490
|
+
* SQLite extensions can be configured in `config/database.yml`.
|
|
1491
|
+
|
|
1492
|
+
The database configuration option `extensions:` allows an application to load SQLite extensions
|
|
1493
|
+
when using `sqlite3` >= v2.4.0. The array members may be filesystem paths or the names of
|
|
1494
|
+
modules that respond to `.to_path`:
|
|
1495
|
+
|
|
1496
|
+
``` yaml
|
|
1497
|
+
development:
|
|
1498
|
+
adapter: sqlite3
|
|
1499
|
+
extensions:
|
|
1500
|
+
- SQLean::UUID # module name responding to `.to_path`
|
|
1501
|
+
- .sqlpkg/nalgeon/crypto/crypto.so # or a filesystem path
|
|
1502
|
+
- <%= AppExtensions.location %> # or ruby code returning a path
|
|
1503
|
+
```
|
|
1504
|
+
|
|
1505
|
+
*Mike Dalessio*
|
|
1506
|
+
|
|
1507
|
+
* `ActiveRecord::Middleware::ShardSelector` supports granular database connection switching.
|
|
1508
|
+
|
|
1509
|
+
A new configuration option, `class_name:`, is introduced to
|
|
1510
|
+
`config.active_record.shard_selector` to allow an application to specify the abstract connection
|
|
1511
|
+
class to be switched by the shard selection middleware. The default class is
|
|
1512
|
+
`ActiveRecord::Base`.
|
|
1513
|
+
|
|
1514
|
+
For example, this configuration tells `ShardSelector` to switch shards using
|
|
1515
|
+
`AnimalsRecord.connected_to`:
|
|
1516
|
+
|
|
1517
|
+
```
|
|
1518
|
+
config.active_record.shard_selector = { class_name: "AnimalsRecord" }
|
|
1519
|
+
```
|
|
1520
|
+
|
|
1521
|
+
*Mike Dalessio*
|
|
1522
|
+
|
|
1523
|
+
* Reset relations after `insert_all`/`upsert_all`.
|
|
1524
|
+
|
|
1525
|
+
Bulk insert/upsert methods will now call `reset` if used on a relation, matching the behavior of `update_all`.
|
|
1526
|
+
|
|
1527
|
+
*Milo Winningham*
|
|
1528
|
+
|
|
1529
|
+
* Use `_N` as a parallel tests databases suffixes
|
|
441
1530
|
|
|
442
|
-
|
|
1531
|
+
Peviously, `-N` was used as a suffix. This can cause problems for RDBMSes
|
|
1532
|
+
which do not support dashes in database names.
|
|
443
1533
|
|
|
444
|
-
|
|
1534
|
+
*fatkodima*
|
|
1535
|
+
|
|
1536
|
+
* Remember when a database connection has recently been verified (for
|
|
1537
|
+
two seconds, by default), to avoid repeated reverifications during a
|
|
1538
|
+
single request.
|
|
1539
|
+
|
|
1540
|
+
This should recreate a similar rate of verification as in Rails 7.1,
|
|
1541
|
+
where connections are leased for the duration of a request, and thus
|
|
1542
|
+
only verified once.
|
|
1543
|
+
|
|
1544
|
+
*Matthew Draper*
|
|
1545
|
+
|
|
1546
|
+
* Allow to reset cache counters for multiple records.
|
|
1547
|
+
|
|
1548
|
+
```
|
|
1549
|
+
Aircraft.reset_counters([1, 2, 3], :wheels_count)
|
|
1550
|
+
```
|
|
1551
|
+
|
|
1552
|
+
It produces much fewer queries compared to the custom implementation using looping over ids.
|
|
1553
|
+
Previously: `O(ids.size * counters.size)` queries, now: `O(ids.size + counters.size)` queries.
|
|
1554
|
+
|
|
1555
|
+
*fatkodima*
|
|
1556
|
+
|
|
1557
|
+
* Add `affected_rows` to `sql.active_record` Notification.
|
|
1558
|
+
|
|
1559
|
+
*Hartley McGuire*
|
|
1560
|
+
|
|
1561
|
+
* Fix `sum` when performing a grouped calculation.
|
|
1562
|
+
|
|
1563
|
+
`User.group(:friendly).sum` no longer worked. This is fixed.
|
|
1564
|
+
|
|
1565
|
+
*Edouard Chin*
|
|
1566
|
+
|
|
1567
|
+
* Add support for enabling or disabling transactional tests per database.
|
|
1568
|
+
|
|
1569
|
+
A test class can now override the default `use_transactional_tests` setting
|
|
1570
|
+
for individual databases, which can be useful if some databases need their
|
|
1571
|
+
current state to be accessible to an external process while tests are running.
|
|
445
1572
|
|
|
446
1573
|
```ruby
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
1574
|
+
class MostlyTransactionalTest < ActiveSupport::TestCase
|
|
1575
|
+
self.use_transactional_tests = true
|
|
1576
|
+
skip_transactional_tests_for_database :shared
|
|
1577
|
+
end
|
|
450
1578
|
```
|
|
451
1579
|
|
|
452
|
-
*
|
|
1580
|
+
*Matthew Cheetham*, *Morgan Mareve*
|
|
1581
|
+
|
|
1582
|
+
* Cast `query_cache` value when using URL configuration.
|
|
1583
|
+
|
|
1584
|
+
*zzak*
|
|
1585
|
+
|
|
1586
|
+
* NULLS NOT DISTINCT works with UNIQUE CONSTRAINT as well as UNIQUE INDEX.
|
|
1587
|
+
|
|
1588
|
+
*Ryuta Kamizono*
|
|
1589
|
+
|
|
1590
|
+
* `PG::UnableToSend: no connection to the server` is now retryable as a connection-related exception
|
|
1591
|
+
|
|
1592
|
+
*Kazuma Watanabe*
|
|
453
1593
|
|
|
454
|
-
Please check [
|
|
1594
|
+
Please check [8-0-stable](https://github.com/rails/rails/blob/8-0-stable/activerecord/CHANGELOG.md) for previous changes.
|