activerecord 7.2.3 → 8.1.3
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 +612 -1055
- data/README.rdoc +1 -1
- data/lib/active_record/association_relation.rb +2 -1
- data/lib/active_record/associations/association.rb +35 -11
- data/lib/active_record/associations/builder/association.rb +23 -11
- data/lib/active_record/associations/builder/belongs_to.rb +17 -4
- 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 +1 -1
- data/lib/active_record/associations/collection_proxy.rb +22 -4
- data/lib/active_record/associations/deprecation.rb +88 -0
- data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
- data/lib/active_record/associations/errors.rb +3 -0
- data/lib/active_record/associations/has_many_through_association.rb +3 -2
- data/lib/active_record/associations/join_dependency.rb +4 -2
- data/lib/active_record/associations/preloader/association.rb +2 -2
- 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/singular_association.rb +8 -3
- data/lib/active_record/associations.rb +192 -24
- data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
- data/lib/active_record/attribute_methods/primary_key.rb +4 -8
- data/lib/active_record/attribute_methods/query.rb +34 -0
- data/lib/active_record/attribute_methods/serialization.rb +16 -3
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -14
- data/lib/active_record/attributes.rb +3 -0
- data/lib/active_record/autosave_association.rb +69 -27
- data/lib/active_record/base.rb +1 -2
- data/lib/active_record/coders/json.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +35 -28
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +16 -4
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +51 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +412 -88
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +137 -75
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +27 -5
- data/lib/active_record/connection_adapters/abstract/quoting.rb +16 -25
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +11 -7
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +32 -35
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +122 -32
- data/lib/active_record/connection_adapters/abstract/transaction.rb +40 -8
- data/lib/active_record/connection_adapters/abstract_adapter.rb +150 -91
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +63 -52
- data/lib/active_record/connection_adapters/column.rb +17 -4
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -4
- data/lib/active_record/connection_adapters/mysql/quoting.rb +0 -8
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +41 -10
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +73 -46
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +89 -94
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +2 -10
- 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 +76 -45
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
- 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 +2 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +9 -17
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +14 -33
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +71 -32
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +139 -63
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +78 -105
- data/lib/active_record/connection_adapters/schema_cache.rb +3 -5
- data/lib/active_record/connection_adapters/sqlite3/column.rb +8 -2
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +90 -98
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +0 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +27 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +13 -14
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +102 -37
- data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +38 -67
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +1 -18
- data/lib/active_record/connection_adapters.rb +1 -56
- data/lib/active_record/connection_handling.rb +25 -2
- data/lib/active_record/core.rb +33 -17
- data/lib/active_record/counter_cache.rb +33 -8
- data/lib/active_record/database_configurations/database_config.rb +9 -1
- data/lib/active_record/database_configurations/hash_config.rb +67 -9
- data/lib/active_record/database_configurations/url_config.rb +13 -3
- data/lib/active_record/database_configurations.rb +7 -3
- data/lib/active_record/delegated_type.rb +1 -1
- data/lib/active_record/dynamic_matchers.rb +54 -69
- data/lib/active_record/encryption/config.rb +3 -1
- data/lib/active_record/encryption/encryptable_record.rb +8 -8
- data/lib/active_record/encryption/encrypted_attribute_type.rb +11 -2
- data/lib/active_record/encryption/encryptor.rb +28 -8
- data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
- data/lib/active_record/encryption/scheme.rb +9 -2
- data/lib/active_record/enum.rb +33 -30
- data/lib/active_record/errors.rb +33 -9
- 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 +73 -0
- data/lib/active_record/fixtures.rb +2 -4
- data/lib/active_record/future_result.rb +15 -9
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +1 -1
- data/lib/active_record/insert_all.rb +14 -9
- data/lib/active_record/locking/optimistic.rb +8 -1
- data/lib/active_record/locking/pessimistic.rb +5 -0
- data/lib/active_record/log_subscriber.rb +3 -13
- data/lib/active_record/middleware/shard_selector.rb +34 -17
- data/lib/active_record/migration/command_recorder.rb +45 -12
- data/lib/active_record/migration/compatibility.rb +37 -24
- data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
- data/lib/active_record/migration.rb +48 -42
- data/lib/active_record/model_schema.rb +38 -13
- data/lib/active_record/nested_attributes.rb +6 -6
- data/lib/active_record/persistence.rb +162 -133
- data/lib/active_record/query_cache.rb +22 -15
- data/lib/active_record/query_logs.rb +100 -52
- data/lib/active_record/query_logs_formatter.rb +17 -28
- data/lib/active_record/querying.rb +8 -8
- data/lib/active_record/railtie.rb +35 -30
- data/lib/active_record/railties/controller_runtime.rb +11 -6
- data/lib/active_record/railties/databases.rake +26 -38
- 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 +53 -21
- data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
- data/lib/active_record/relation/batches.rb +147 -73
- data/lib/active_record/relation/calculations.rb +52 -40
- data/lib/active_record/relation/delegation.rb +25 -15
- data/lib/active_record/relation/finder_methods.rb +40 -24
- data/lib/active_record/relation/merger.rb +8 -8
- data/lib/active_record/relation/predicate_builder/array_handler.rb +3 -1
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +9 -9
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +8 -8
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
- data/lib/active_record/relation/predicate_builder.rb +22 -7
- data/lib/active_record/relation/query_attribute.rb +3 -1
- data/lib/active_record/relation/query_methods.rb +140 -86
- data/lib/active_record/relation/spawn_methods.rb +7 -7
- data/lib/active_record/relation/where_clause.rb +2 -9
- data/lib/active_record/relation.rb +107 -75
- data/lib/active_record/result.rb +109 -24
- data/lib/active_record/runtime_registry.rb +42 -58
- data/lib/active_record/sanitization.rb +9 -6
- data/lib/active_record/schema_dumper.rb +18 -11
- data/lib/active_record/schema_migration.rb +2 -1
- data/lib/active_record/scoping/named.rb +5 -2
- data/lib/active_record/scoping.rb +0 -1
- data/lib/active_record/signed_id.rb +43 -15
- data/lib/active_record/statement_cache.rb +24 -20
- data/lib/active_record/store.rb +51 -22
- data/lib/active_record/structured_event_subscriber.rb +85 -0
- data/lib/active_record/table_metadata.rb +6 -23
- data/lib/active_record/tasks/abstract_tasks.rb +76 -0
- data/lib/active_record/tasks/database_tasks.rb +85 -85
- data/lib/active_record/tasks/mysql_database_tasks.rb +3 -42
- data/lib/active_record/tasks/postgresql_database_tasks.rb +7 -40
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -28
- data/lib/active_record/test_databases.rb +14 -4
- data/lib/active_record/test_fixtures.rb +39 -2
- data/lib/active_record/testing/query_assertions.rb +8 -2
- data/lib/active_record/timestamp.rb +4 -2
- data/lib/active_record/token_for.rb +1 -1
- data/lib/active_record/transaction.rb +2 -5
- data/lib/active_record/transactions.rb +37 -16
- 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/validations/uniqueness.rb +8 -8
- data/lib/active_record.rb +84 -49
- data/lib/arel/alias_predication.rb +2 -0
- data/lib/arel/collectors/bind.rb +2 -2
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +2 -2
- data/lib/arel/crud.rb +6 -11
- data/lib/arel/nodes/binary.rb +1 -1
- data/lib/arel/nodes/count.rb +2 -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.rb +0 -2
- data/lib/arel/predications.rb +1 -3
- data/lib/arel/select_manager.rb +7 -2
- data/lib/arel/table.rb +3 -7
- data/lib/arel/visitors/dot.rb +0 -3
- data/lib/arel/visitors/postgresql.rb +55 -0
- data/lib/arel/visitors/sqlite.rb +55 -8
- data/lib/arel/visitors/to_sql.rb +3 -21
- data/lib/arel.rb +3 -1
- data/lib/rails/generators/active_record/application_record/USAGE +1 -1
- metadata +16 -13
- data/lib/active_record/explain_subscriber.rb +0 -34
- data/lib/active_record/normalization.rb +0 -163
- data/lib/active_record/relation/record_fetch_warning.rb +0 -52
data/CHANGELOG.md
CHANGED
|
@@ -1,1415 +1,972 @@
|
|
|
1
|
-
## Rails
|
|
1
|
+
## Rails 8.1.3 (March 24, 2026) ##
|
|
2
2
|
|
|
3
|
-
* Fix
|
|
4
|
-
|
|
5
|
-
When altering a table in SQLite3 that is referenced by child tables with
|
|
6
|
-
`ON DELETE CASCADE` foreign keys, ActiveRecord would silently delete all
|
|
7
|
-
data from the child tables. This occurred because SQLite requires table
|
|
8
|
-
recreation for schema changes, and during this process the original table
|
|
9
|
-
is temporarily dropped, triggering CASCADE deletes on child tables.
|
|
10
|
-
|
|
11
|
-
The root cause was incorrect ordering of operations. The original code
|
|
12
|
-
wrapped `disable_referential_integrity` inside a transaction, but
|
|
13
|
-
`PRAGMA foreign_keys` cannot be modified inside a transaction in SQLite -
|
|
14
|
-
attempting to do so simply has no effect. This meant foreign keys remained
|
|
15
|
-
enabled during table recreation, causing CASCADE deletes to fire.
|
|
16
|
-
|
|
17
|
-
The fix reverses the order to follow the official SQLite 12-step ALTER TABLE
|
|
18
|
-
procedure: `disable_referential_integrity` now wraps the transaction instead
|
|
19
|
-
of being wrapped by it. This ensures foreign keys are properly disabled
|
|
20
|
-
before the transaction starts and re-enabled after it commits, preventing
|
|
21
|
-
CASCADE deletes while maintaining data integrity through atomic transactions.
|
|
22
|
-
|
|
23
|
-
*Ruy Rocha*
|
|
24
|
-
|
|
25
|
-
* Fix `belongs_to` associations not to clear the entire composite primary key.
|
|
3
|
+
* Fix `insert_all` and `upsert_all` log message when called on anonymous classes.
|
|
26
4
|
|
|
27
|
-
|
|
28
|
-
only the optional part of the key should be cleared.
|
|
5
|
+
*Gabriel Sobrinho*
|
|
29
6
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
* Fix invalid records being autosaved when distantly associated records are marked for deletion.
|
|
33
|
-
|
|
34
|
-
*Ian Terrell*, *axlekb AB*
|
|
35
|
-
|
|
36
|
-
* Prevent persisting invalid record.
|
|
37
|
-
|
|
38
|
-
*Edouard Chin*
|
|
39
|
-
|
|
40
|
-
* Fix count with group by qualified name on loaded relation.
|
|
41
|
-
|
|
42
|
-
*Ryuta Kamizono*
|
|
43
|
-
|
|
44
|
-
* Fix `sum` with qualified name on loaded relation.
|
|
45
|
-
|
|
46
|
-
*Chris Gunther*
|
|
7
|
+
* Respect `ActiveRecord::SchemaDumper.ignore_tables` when dumping SQLite virtual tables.
|
|
47
8
|
|
|
48
|
-
*
|
|
9
|
+
*Hans Schnedlitz*
|
|
49
10
|
|
|
50
|
-
|
|
11
|
+
* Restore previous instrumenter after `execute_or_skip`
|
|
51
12
|
|
|
52
|
-
|
|
13
|
+
`FutureResult#execute_or_skip` replaces the thread's instrumenter with an
|
|
14
|
+
`EventBuffer` to collect events published during async query execution.
|
|
15
|
+
If the global async executor is saturated and the `caller_runs` fallback
|
|
16
|
+
executes the task on the calling thread, we need to make sure the previous
|
|
17
|
+
instrumenter is restored or the stale `EventBuffer` would stay in place and
|
|
18
|
+
permanently swallow all subsequent `sql.active_record` notifications on
|
|
19
|
+
that thread.
|
|
53
20
|
|
|
54
|
-
|
|
55
|
-
for each thread.
|
|
21
|
+
*Rosa Gutierrez*
|
|
56
22
|
|
|
57
|
-
|
|
23
|
+
* Bump the minimum PostgreSQL version to 9.5, due to usage of `array_position` function.
|
|
58
24
|
|
|
59
|
-
*
|
|
25
|
+
*Ivan Kuchin*
|
|
60
26
|
|
|
61
|
-
*
|
|
27
|
+
* Fix Ruby 4.0 delegator warning when calling inspect on ActiveRecord::Type::Serialized.
|
|
62
28
|
|
|
63
|
-
*
|
|
64
|
-
|
|
65
|
-
* Fix false positive change detection involving STI and polymorhic has one relationships.
|
|
29
|
+
*Hammad Khan*
|
|
66
30
|
|
|
67
|
-
|
|
68
|
-
class, causing nedless extra autosaves.
|
|
31
|
+
* Fix support for table names containing hyphens.
|
|
69
32
|
|
|
70
|
-
*
|
|
33
|
+
*Evgeniy Demin*
|
|
71
34
|
|
|
72
|
-
* Fix
|
|
35
|
+
* Fix column deduplication for SQLite3 and PostgreSQL virtual (generated) columns.
|
|
73
36
|
|
|
74
|
-
|
|
37
|
+
`Column#==` and `Column#hash` now account for `virtual?` so that the
|
|
38
|
+
`Deduplicable` registry does not treat a generated column and a regular
|
|
39
|
+
column with the same name and type as identical. Previously, if a
|
|
40
|
+
generated column was registered first, a regular column on a different
|
|
41
|
+
table could be deduplicated to the generated instance, silently
|
|
42
|
+
excluding it from INSERT/UPDATE statements.
|
|
75
43
|
|
|
76
|
-
*
|
|
44
|
+
*Jay Huber*
|
|
77
45
|
|
|
78
|
-
|
|
46
|
+
* Fix PostgreSQL schema dumping to handle schema-qualified table names in foreign_key references that span different schemas.
|
|
79
47
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
base = Comment.joins(:post).where(user_id: 1).where("recent = 1")
|
|
84
|
-
puts base.merge(base.where(draft: true).or(Post.where(archived: true))).to_sql
|
|
85
|
-
```
|
|
48
|
+
# before
|
|
49
|
+
add_foreign_key "hst.event_log_attributes", "hst.event_logs" # emits correctly because they're in the same schema (hst)
|
|
50
|
+
add_foreign_key "hst.event_log_attributes", "hst.usr.user_profiles", column: "created_by_id" # emits hst.user.* when user.* is expected
|
|
86
51
|
|
|
87
|
-
|
|
52
|
+
# after
|
|
53
|
+
add_foreign_key "hst.event_log_attributes", "hst.event_logs"
|
|
54
|
+
add_foreign_key "hst.event_log_attributes", "usr.user_profiles", column: "created_by_id"
|
|
88
55
|
|
|
89
|
-
|
|
90
|
-
SELECT "comments".* FROM "comments"
|
|
91
|
-
INNER JOIN "posts" ON "posts"."id" = "comments"."post_id"
|
|
92
|
-
WHERE (recent = 1)
|
|
93
|
-
AND (
|
|
94
|
-
"comments"."user_id" = 1
|
|
95
|
-
AND (recent = 1)
|
|
96
|
-
AND "comments"."draft" = 1
|
|
97
|
-
OR "posts"."archived" = 1
|
|
98
|
-
)
|
|
99
|
-
```
|
|
56
|
+
*Chiperific*
|
|
100
57
|
|
|
101
|
-
After:
|
|
102
58
|
|
|
103
|
-
|
|
104
|
-
SELECT "comments".* FROM "comments"
|
|
105
|
-
INNER JOIN "posts" ON "posts"."id" = "comments"."post_id"
|
|
106
|
-
WHERE "comments"."user_id" = 1
|
|
107
|
-
AND (recent = 1)
|
|
108
|
-
AND (
|
|
109
|
-
"comments"."user_id" = 1
|
|
110
|
-
AND (recent = 1)
|
|
111
|
-
AND "comments"."draft" = 1
|
|
112
|
-
OR "posts"."archived" = 1
|
|
113
|
-
)
|
|
114
|
-
```
|
|
59
|
+
## Rails 8.1.2.1 (March 23, 2026) ##
|
|
115
60
|
|
|
116
|
-
|
|
61
|
+
* No changes.
|
|
117
62
|
|
|
118
|
-
* Fix inline `has_and_belongs_to_many` fixtures for tables with composite primary keys.
|
|
119
63
|
|
|
120
|
-
|
|
64
|
+
## Rails 8.1.2 (January 08, 2026) ##
|
|
121
65
|
|
|
122
|
-
* Fix
|
|
66
|
+
* Fix counting cached queries in `ActiveRecord::RuntimeRegistry`.
|
|
123
67
|
|
|
124
68
|
*fatkodima*
|
|
125
69
|
|
|
126
|
-
* Fix
|
|
127
|
-
loaded `has_and_belongs_to_many` association.
|
|
128
|
-
|
|
129
|
-
*Hartley McGuire*
|
|
130
|
-
|
|
131
|
-
* Fix inline has_and_belongs_to_many fixtures for tables with composite primary keys.
|
|
70
|
+
* Fix merging relations with arel equality predicates with null relations.
|
|
132
71
|
|
|
133
72
|
*fatkodima*
|
|
134
73
|
|
|
135
|
-
*
|
|
136
|
-
|
|
137
|
-
When using `create_or_find_by`, raising a ActiveRecord::Rollback error
|
|
138
|
-
in a `after_save` callback had no effect, the transaction was committed
|
|
139
|
-
and a record created.
|
|
140
|
-
|
|
141
|
-
*Edouard Chin*
|
|
74
|
+
* Fix SQLite3 schema dump for non-autoincrement integer primary keys.
|
|
142
75
|
|
|
143
|
-
|
|
76
|
+
Previously, `schema.rb` should incorrectly restore that table with an auto incrementing
|
|
77
|
+
primary key.
|
|
144
78
|
|
|
145
|
-
|
|
79
|
+
*Chris Hasiński*
|
|
146
80
|
|
|
147
|
-
|
|
148
|
-
the most common being with the PostgreSQLAdapter raising `undefined method 'key?' for nil`
|
|
149
|
-
or `TypeError: wrong argument type nil (expected PG::TypeMap)`.
|
|
150
|
-
|
|
151
|
-
*Jean Boussier*
|
|
152
|
-
|
|
153
|
-
* The SQLite3 adapter quotes non-finite Numeric values like "Infinity" and "NaN".
|
|
154
|
-
|
|
155
|
-
*Mike Dalessio*
|
|
81
|
+
* Fix PostgreSQL `schema_search_path` not being reapplied after `reset!` or `reconnect!`.
|
|
156
82
|
|
|
157
|
-
|
|
83
|
+
The `schema_search_path` configured in `database.yml` is now correctly
|
|
84
|
+
reapplied instead of falling back to PostgreSQL defaults.
|
|
158
85
|
|
|
159
|
-
|
|
160
|
-
comparing it with the minimum required version for the adapter. This meant that the connection could
|
|
161
|
-
never be successfully configured on subsequent reconnection attempts.
|
|
86
|
+
*Tobias Egli*
|
|
162
87
|
|
|
163
|
-
|
|
164
|
-
and ensuring the version isn't cached, which allows the version to be retrieved on the next connection attempt.
|
|
165
|
-
|
|
166
|
-
*Joshua Young*, *Rian McGuire*
|
|
167
|
-
|
|
168
|
-
* Fix error handling during connection configuration.
|
|
169
|
-
|
|
170
|
-
Active Record wasn't properly handling errors during the connection configuration phase.
|
|
171
|
-
This could lead to a partially configured connection being used, resulting in various exceptions,
|
|
172
|
-
the most common being with the PostgreSQLAdapter raising `undefined method `key?' for nil`
|
|
173
|
-
or `TypeError: wrong argument type nil (expected PG::TypeMap)`.
|
|
174
|
-
|
|
175
|
-
*Jean Boussier*
|
|
176
|
-
|
|
177
|
-
* Fix a case where a non-retryable query could be marked retryable.
|
|
178
|
-
|
|
179
|
-
*Hartley McGuire*
|
|
180
|
-
|
|
181
|
-
* Handle circular references when autosaving associations.
|
|
182
|
-
|
|
183
|
-
*zzak*
|
|
184
|
-
|
|
185
|
-
* Prevent persisting invalid record.
|
|
186
|
-
|
|
187
|
-
*Edouard Chin*
|
|
188
|
-
|
|
189
|
-
* Fix support for PostgreSQL enum types with commas in their name.
|
|
190
|
-
|
|
191
|
-
*Arthur Hess*
|
|
192
|
-
|
|
193
|
-
* Fix inserts on MySQL with no RETURNING support for a table with multiple auto populated columns.
|
|
194
|
-
|
|
195
|
-
*Nikita Vasilevsky*
|
|
196
|
-
|
|
197
|
-
* Fix joining on a scoped association with string joins and bind parameters.
|
|
88
|
+
* Restore the ability of enum to be foats.
|
|
198
89
|
|
|
199
90
|
```ruby
|
|
200
|
-
|
|
201
|
-
has_many :instructor_roles, -> { active }
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
class InstructorRole < ActiveRecord::Base
|
|
205
|
-
scope :active, -> {
|
|
206
|
-
joins("JOIN students ON instructor_roles.student_id = students.id")
|
|
207
|
-
.where(students { status: 1 })
|
|
208
|
-
}
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
Instructor.joins(:instructor_roles).first
|
|
91
|
+
enum :rating, { low: 0.0, medium: 0.5, high: 1.0 },
|
|
212
92
|
```
|
|
213
93
|
|
|
214
|
-
|
|
215
|
-
`active` scope bind parameters would be lost.
|
|
216
|
-
|
|
217
|
-
*Jean Boussier*
|
|
218
|
-
|
|
219
|
-
* Fix a potential race condition with system tests and transactional fixtures.
|
|
220
|
-
|
|
221
|
-
*Sjoerd Lagarde*
|
|
94
|
+
In Rails 8.1.0, enum values are eagerly validated, and floats weren't expected.
|
|
222
95
|
|
|
223
|
-
*
|
|
96
|
+
*Said Kaldybaev*
|
|
224
97
|
|
|
225
|
-
|
|
98
|
+
* Ensure batched preloaded associations accounts for klass when grouping to avoid issues with STI.
|
|
226
99
|
|
|
227
|
-
*
|
|
100
|
+
*zzak*, *Stjepan Hadjic*
|
|
228
101
|
|
|
229
|
-
|
|
102
|
+
* Fix `ActiveRecord::SoleRecordExceeded#record` to return the relation.
|
|
230
103
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
Active Record was incorrectly performing validation on associated record that
|
|
234
|
-
weren't created nor modified as part of the transaction:
|
|
235
|
-
|
|
236
|
-
```ruby
|
|
237
|
-
Post.create!(author: User.find(1)) # Fail if user is invalid
|
|
238
|
-
```
|
|
104
|
+
This was the case until Rails 7.2, but starting from 8.0 it
|
|
105
|
+
started mistakenly returning the model class.
|
|
239
106
|
|
|
240
107
|
*Jean Boussier*
|
|
241
108
|
|
|
242
|
-
*
|
|
243
|
-
two seconds, by default), to avoid repeated reverifications during a
|
|
244
|
-
single request.
|
|
245
|
-
|
|
246
|
-
This should recreate a similar rate of verification as in Rails 7.1,
|
|
247
|
-
where connections are leased for the duration of a request, and thus
|
|
248
|
-
only verified once.
|
|
249
|
-
|
|
250
|
-
*Matthew Draper*
|
|
251
|
-
|
|
252
|
-
* Fix prepared statements on mysql2 adapter.
|
|
253
|
-
|
|
254
|
-
*Jean Boussier*
|
|
255
|
-
|
|
256
|
-
* Fix a race condition in `ActiveRecord::Base#method_missing` when lazily defining attributes.
|
|
257
|
-
|
|
258
|
-
If multiple thread were concurrently triggering attribute definition on the same model,
|
|
259
|
-
it could result in a `NoMethodError` being raised.
|
|
260
|
-
|
|
261
|
-
*Jean Boussier*
|
|
262
|
-
|
|
263
|
-
* Fix MySQL default functions getting dropped when changing a column's nullability.
|
|
264
|
-
|
|
265
|
-
*Bastian Bartmann*
|
|
266
|
-
|
|
267
|
-
* Fix `add_unique_constraint`/`add_check_constraint`/`/`add_foreign_key` to be revertible when
|
|
268
|
-
given invalid options.
|
|
269
|
-
|
|
270
|
-
*fatkodima*
|
|
271
|
-
|
|
272
|
-
* Fix asynchronous destroying of polymorphic `belongs_to` associations.
|
|
273
|
-
|
|
274
|
-
*fatkodima*
|
|
275
|
-
|
|
276
|
-
* NOT VALID constraints should not dump in `create_table`.
|
|
277
|
-
|
|
278
|
-
*Ryuta Kamizono*
|
|
279
|
-
|
|
280
|
-
* Fix finding by nil composite primary key association.
|
|
281
|
-
|
|
282
|
-
*fatkodima*
|
|
283
|
-
|
|
284
|
-
* Fix parsing of SQLite foreign key names when they contain non-ASCII characters
|
|
285
|
-
|
|
286
|
-
*Zacharias Knudsen*
|
|
287
|
-
|
|
288
|
-
* Fix parsing of MySQL 8.0.16+ CHECK constraints when they contain new lines.
|
|
289
|
-
|
|
290
|
-
*Steve Hill*
|
|
291
|
-
|
|
292
|
-
* Ensure normalized attribute queries use `IS NULL` consistently for `nil` and normalized `nil` values.
|
|
293
|
-
|
|
294
|
-
*Joshua Young*
|
|
295
|
-
|
|
296
|
-
* Restore back the ability to pass only database name for `DATABASE_URL`.
|
|
297
|
-
|
|
298
|
-
*fatkodima*
|
|
299
|
-
|
|
300
|
-
* Fix `order` with using association name as an alias.
|
|
301
|
-
|
|
302
|
-
*Ryuta Kamizono*
|
|
303
|
-
|
|
304
|
-
* Improve invalid argument error for with.
|
|
305
|
-
|
|
306
|
-
*Ryuta Kamizono*
|
|
307
|
-
|
|
308
|
-
* Deduplicate `with` CTE expressions.
|
|
309
|
-
|
|
310
|
-
*fatkodima*
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
## Rails 7.2.2.2 (August 13, 2025) ##
|
|
314
|
-
|
|
315
|
-
* Call inspect on ids in RecordNotFound error
|
|
316
|
-
|
|
317
|
-
[CVE-2025-55193]
|
|
109
|
+
* Improve PostgreSQLAdapter resilience to Timeout.timeout.
|
|
318
110
|
|
|
319
|
-
|
|
111
|
+
Better handle asynchronous exceptions being thrown inside
|
|
112
|
+
the `reconnect!` method.
|
|
320
113
|
|
|
114
|
+
This may fixes some deep errors such as:
|
|
321
115
|
|
|
322
|
-
## Rails 7.2.2.1 (December 10, 2024) ##
|
|
323
|
-
|
|
324
|
-
* No changes.
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
## Rails 7.2.2 (October 30, 2024) ##
|
|
328
|
-
|
|
329
|
-
* Fix support for `query_cache: false` in `database.yml`.
|
|
330
|
-
|
|
331
|
-
`query_cache: false` would no longer entirely disable the Active Record query cache.
|
|
332
|
-
|
|
333
|
-
*zzak*
|
|
334
|
-
|
|
335
|
-
* Set `.attributes_for_inspect` to `:all` by default.
|
|
336
|
-
|
|
337
|
-
For new applications it is set to `[:id]` in config/environment/production.rb.
|
|
338
|
-
|
|
339
|
-
In the console all the attributes are always shown.
|
|
340
|
-
|
|
341
|
-
*Andrew Novoselac*
|
|
342
|
-
|
|
343
|
-
* `PG::UnableToSend: no connection to the server` is now retryable as a connection-related exception
|
|
344
|
-
|
|
345
|
-
*Kazuma Watanabe*
|
|
346
|
-
|
|
347
|
-
* Fix marshalling of unsaved associated records in 7.1 format.
|
|
348
|
-
|
|
349
|
-
The 7.1 format would only marshal associated records if the association was loaded.
|
|
350
|
-
But associations that would only contain unsaved records would be skipped.
|
|
351
|
-
|
|
352
|
-
*Jean Boussier*
|
|
353
|
-
|
|
354
|
-
* Fix incorrect SQL query when passing an empty hash to `ActiveRecord::Base.insert`.
|
|
355
|
-
|
|
356
|
-
*David Stosik*
|
|
357
|
-
|
|
358
|
-
* Allow to save records with polymorphic join tables that have `inverse_of`
|
|
359
|
-
specified.
|
|
360
|
-
|
|
361
|
-
*Markus Doits*
|
|
362
|
-
|
|
363
|
-
* Fix association scopes applying on the incorrect join when using a polymorphic `has_many through:`.
|
|
364
|
-
|
|
365
|
-
*Joshua Young*
|
|
366
|
-
|
|
367
|
-
* Fix `dependent: :destroy` for bi-directional has one through association.
|
|
368
|
-
|
|
369
|
-
Fixes #50948.
|
|
370
|
-
|
|
371
|
-
```ruby
|
|
372
|
-
class Left < ActiveRecord::Base
|
|
373
|
-
has_one :middle, dependent: :destroy
|
|
374
|
-
has_one :right, through: :middle
|
|
375
|
-
end
|
|
376
|
-
|
|
377
|
-
class Middle < ActiveRecord::Base
|
|
378
|
-
belongs_to :left, dependent: :destroy
|
|
379
|
-
belongs_to :right, dependent: :destroy
|
|
380
|
-
end
|
|
381
|
-
|
|
382
|
-
class Right < ActiveRecord::Base
|
|
383
|
-
has_one :middle, dependent: :destroy
|
|
384
|
-
has_one :left, through: :middle
|
|
385
|
-
end
|
|
386
116
|
```
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
*Andy Stewart*
|
|
391
|
-
|
|
392
|
-
* Properly handle lazily pinned connection pools.
|
|
393
|
-
|
|
394
|
-
Fixes #53147.
|
|
395
|
-
|
|
396
|
-
When using transactional fixtures with system tests to similar tools
|
|
397
|
-
such as capybara, it could happen that a connection end up pinned by the
|
|
398
|
-
server thread rather than the test thread, causing
|
|
399
|
-
`"Cannot expire connection, it is owned by a different thread"` errors.
|
|
400
|
-
|
|
401
|
-
*Jean Boussier*
|
|
402
|
-
|
|
403
|
-
* Fix `ActiveRecord::Base.with` to accept more than two sub queries.
|
|
404
|
-
|
|
405
|
-
Fixes #53110.
|
|
406
|
-
|
|
407
|
-
```ruby
|
|
408
|
-
User.with(foo: [User.select(:id), User.select(:id), User.select(:id)]).to_sql
|
|
409
|
-
undefined method `union' for an instance of Arel::Nodes::UnionAll (NoMethodError)
|
|
117
|
+
undefined method `key?' for nil:NilClass (NoMethodError)
|
|
118
|
+
if !type_map.key?(oid)
|
|
410
119
|
```
|
|
411
120
|
|
|
412
|
-
The above now works as expected.
|
|
413
|
-
|
|
414
|
-
*fatkodima*
|
|
415
|
-
|
|
416
|
-
* Properly release pinned connections with non joinable connections.
|
|
417
|
-
|
|
418
|
-
Fixes #52973
|
|
419
|
-
|
|
420
|
-
When running system tests with transactional fixtures on, it could happen that
|
|
421
|
-
the connection leased by the Puma thread wouldn't be properly released back to the pool,
|
|
422
|
-
causing "Cannot expire connection, it is owned by a different thread" errors in later tests.
|
|
423
|
-
|
|
424
121
|
*Jean Boussier*
|
|
425
122
|
|
|
426
|
-
*
|
|
427
|
-
|
|
428
|
-
Fixes #52742
|
|
429
|
-
|
|
430
|
-
*Ryota Kitazawa*, *Takayuki Nagatomi*
|
|
431
|
-
|
|
432
|
-
* Fix an issue where `.left_outer_joins` used with multiple associations that have
|
|
433
|
-
the same child association but different parents does not join all parents.
|
|
123
|
+
* Fix structured events for Active Record was not being emitted.
|
|
434
124
|
|
|
435
|
-
|
|
125
|
+
*Yuji Yaginuma*
|
|
436
126
|
|
|
437
|
-
|
|
127
|
+
* Fix `eager_load` when loading `has_many` assocations with composite primary keys.
|
|
438
128
|
|
|
439
|
-
|
|
129
|
+
This would result in some records being loaded multiple times.
|
|
440
130
|
|
|
441
|
-
*
|
|
131
|
+
*Martin-Alexander*
|
|
442
132
|
|
|
443
|
-
* Ensure `ActiveRecord::Encryption.config` is always ready before access.
|
|
444
133
|
|
|
445
|
-
|
|
446
|
-
was loaded. Therefore, accessing `ActiveRecord::Encryption.config` properties before
|
|
447
|
-
`ActiveRecord::Base` was loaded would give incorrect results.
|
|
448
|
-
|
|
449
|
-
`ActiveRecord::Encryption` now has its own loading hook so that its configuration is set as
|
|
450
|
-
soon as needed.
|
|
451
|
-
|
|
452
|
-
When `ActiveRecord::Base` is loaded, even lazily, it in turn triggers the loading of
|
|
453
|
-
`ActiveRecord::Encryption`, thus preserving the original behavior of having its config ready
|
|
454
|
-
before any use of `ActiveRecord::Base`.
|
|
455
|
-
|
|
456
|
-
*Maxime Réty*
|
|
457
|
-
|
|
458
|
-
* Add `TimeZoneConverter#==` method, so objects will be properly compared by
|
|
459
|
-
their type, scale, limit & precision.
|
|
460
|
-
|
|
461
|
-
Address #52699.
|
|
462
|
-
|
|
463
|
-
*Ruy Rocha*
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
## Rails 7.2.1.2 (October 23, 2024) ##
|
|
134
|
+
## Rails 8.1.1 (October 28, 2025) ##
|
|
467
135
|
|
|
468
136
|
* No changes.
|
|
469
137
|
|
|
470
138
|
|
|
471
|
-
## Rails
|
|
472
|
-
|
|
473
|
-
* No changes.
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
## Rails 7.2.1 (August 22, 2024) ##
|
|
477
|
-
|
|
478
|
-
* Fix detection for `enum` columns with parallelized tests and PostgreSQL.
|
|
479
|
-
|
|
480
|
-
*Rafael Mendonça França*
|
|
481
|
-
|
|
482
|
-
* Allow to eager load nested nil associations.
|
|
483
|
-
|
|
484
|
-
*fatkodima*
|
|
485
|
-
|
|
486
|
-
* Fix swallowing ignore order warning when batching using `BatchEnumerator`.
|
|
487
|
-
|
|
488
|
-
*fatkodima*
|
|
489
|
-
|
|
490
|
-
* Fix memory bloat on the connection pool when using the Fiber `IsolatedExecutionState`.
|
|
491
|
-
|
|
492
|
-
*Jean Boussier*
|
|
493
|
-
|
|
494
|
-
* Restore inferred association class with the same modularized name.
|
|
495
|
-
|
|
496
|
-
*Justin Ko*
|
|
497
|
-
|
|
498
|
-
* Fix `ActiveRecord::Base.inspect` to properly explain how to load schema information.
|
|
499
|
-
|
|
500
|
-
*Jean Boussier*
|
|
501
|
-
|
|
502
|
-
* Check invalid `enum` options for the new syntax.
|
|
503
|
-
|
|
504
|
-
The options using `_` prefix in the old syntax are invalid in the new syntax.
|
|
139
|
+
## Rails 8.1.0 (October 22, 2025) ##
|
|
505
140
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
* Fix `ActiveRecord::Encryption::EncryptedAttributeType#type` to return
|
|
509
|
-
actual cast type.
|
|
510
|
-
|
|
511
|
-
*Vasiliy Ermolovich*
|
|
512
|
-
|
|
513
|
-
* Fix `create_table` with `:auto_increment` option for MySQL adapter.
|
|
514
|
-
|
|
515
|
-
*fatkodima*
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
## Rails 7.2.0 (August 09, 2024) ##
|
|
519
|
-
|
|
520
|
-
* Handle commas in Sqlite3 default function definitions.
|
|
521
|
-
|
|
522
|
-
*Stephen Margheim*
|
|
523
|
-
|
|
524
|
-
* Fixes `validates_associated` raising an exception when configured with a
|
|
525
|
-
singular association and having `index_nested_attribute_errors` enabled.
|
|
526
|
-
|
|
527
|
-
*Martin Spickermann*
|
|
528
|
-
|
|
529
|
-
* The constant `ActiveRecord::ImmutableRelation` has been deprecated because
|
|
530
|
-
we want to reserve that name for a stronger sense of "immutable relation".
|
|
531
|
-
Please use `ActiveRecord::UnmodifiableRelation` instead.
|
|
532
|
-
|
|
533
|
-
*Xavier Noria*
|
|
534
|
-
|
|
535
|
-
* Add condensed `#inspect` for `ConnectionPool`, `AbstractAdapter`, and
|
|
536
|
-
`DatabaseConfig`.
|
|
537
|
-
|
|
538
|
-
*Hartley McGuire*
|
|
539
|
-
|
|
540
|
-
* Fixed a memory performance issue in Active Record attribute methods definition.
|
|
541
|
-
|
|
542
|
-
*Jean Boussier*
|
|
543
|
-
|
|
544
|
-
* Define the new Active Support notification event `start_transaction.active_record`.
|
|
545
|
-
|
|
546
|
-
This event is fired when database transactions or savepoints start, and
|
|
547
|
-
complements `transaction.active_record`, which is emitted when they finish.
|
|
548
|
-
|
|
549
|
-
The payload has the transaction (`:transaction`) and the connection (`:connection`).
|
|
550
|
-
|
|
551
|
-
*Xavier Noria*
|
|
552
|
-
|
|
553
|
-
* Fix an issue where the IDs reader method did not return expected results
|
|
554
|
-
for preloaded associations in models using composite primary keys.
|
|
555
|
-
|
|
556
|
-
*Jay Ang*
|
|
557
|
-
|
|
558
|
-
* The payload of `sql.active_record` Active Support notifications now has the current transaction in the `:transaction` key.
|
|
559
|
-
|
|
560
|
-
*Xavier Noria*
|
|
561
|
-
|
|
562
|
-
* The payload of `transaction.active_record` Active Support notifications now has the transaction the event is related to in the `:transaction` key.
|
|
563
|
-
|
|
564
|
-
*Xavier Noria*
|
|
565
|
-
|
|
566
|
-
* Define `ActiveRecord::Transaction#uuid`, which returns a UUID for the database transaction. This may be helpful when tracing database activity. These UUIDs are generated only on demand.
|
|
567
|
-
|
|
568
|
-
*Xavier Noria*
|
|
569
|
-
|
|
570
|
-
* Fix inference of association model on nested models with the same demodularized name.
|
|
571
|
-
|
|
572
|
-
E.g. with the following setup:
|
|
573
|
-
|
|
574
|
-
```ruby
|
|
575
|
-
class Nested::Post < ApplicationRecord
|
|
576
|
-
has_one :post, through: :other
|
|
577
|
-
end
|
|
578
|
-
```
|
|
579
|
-
|
|
580
|
-
Before, `#post` would infer the model as `Nested::Post`, but now it correctly infers `Post`.
|
|
581
|
-
|
|
582
|
-
*Joshua Young*
|
|
583
|
-
|
|
584
|
-
* PostgreSQL `Cidr#change?` detects the address prefix change.
|
|
585
|
-
|
|
586
|
-
*Taketo Takashima*
|
|
587
|
-
|
|
588
|
-
* Change `BatchEnumerator#destroy_all` to return the total number of affected rows.
|
|
589
|
-
|
|
590
|
-
Previously, it always returned `nil`.
|
|
591
|
-
|
|
592
|
-
*fatkodima*
|
|
593
|
-
|
|
594
|
-
* Support `touch_all` in batches.
|
|
595
|
-
|
|
596
|
-
```ruby
|
|
597
|
-
Post.in_batches.touch_all
|
|
598
|
-
```
|
|
599
|
-
|
|
600
|
-
*fatkodima*
|
|
601
|
-
|
|
602
|
-
* Add support for `:if_not_exists` and `:force` options to `create_schema`.
|
|
603
|
-
|
|
604
|
-
*fatkodima*
|
|
605
|
-
|
|
606
|
-
* Fix `index_errors` having incorrect index in association validation errors.
|
|
607
|
-
|
|
608
|
-
*lulalala*
|
|
609
|
-
|
|
610
|
-
* Add `index_errors: :nested_attributes_order` mode.
|
|
611
|
-
|
|
612
|
-
This indexes the association validation errors based on the order received by nested attributes setter, and respects the `reject_if` configuration. This enables API to provide enough information to the frontend to map the validation errors back to their respective form fields.
|
|
613
|
-
|
|
614
|
-
*lulalala*
|
|
615
|
-
|
|
616
|
-
* Add `Rails.application.config.active_record.postgresql_adapter_decode_dates` to opt out of decoding dates automatically with the postgresql adapter. Defaults to true.
|
|
617
|
-
|
|
618
|
-
*Joé Dupuis*
|
|
619
|
-
|
|
620
|
-
* Association option `query_constraints` is deprecated in favor of `foreign_key`.
|
|
141
|
+
* Fix SQLite3 data loss during table alterations with CASCADE foreign keys.
|
|
621
142
|
|
|
622
|
-
|
|
143
|
+
When altering a table in SQLite3 that is referenced by child tables with
|
|
144
|
+
`ON DELETE CASCADE` foreign keys, ActiveRecord would silently delete all
|
|
145
|
+
data from the child tables. This occurred because SQLite requires table
|
|
146
|
+
recreation for schema changes, and during this process the original table
|
|
147
|
+
is temporarily dropped, triggering CASCADE deletes on child tables.
|
|
623
148
|
|
|
624
|
-
|
|
149
|
+
The root cause was incorrect ordering of operations. The original code
|
|
150
|
+
wrapped `disable_referential_integrity` inside a transaction, but
|
|
151
|
+
`PRAGMA foreign_keys` cannot be modified inside a transaction in SQLite -
|
|
152
|
+
attempting to do so simply has no effect. This meant foreign keys remained
|
|
153
|
+
enabled during table recreation, causing CASCADE deletes to fire.
|
|
625
154
|
|
|
626
|
-
|
|
155
|
+
The fix reverses the order to follow the official SQLite 12-step ALTER TABLE
|
|
156
|
+
procedure: `disable_referential_integrity` now wraps the transaction instead
|
|
157
|
+
of being wrapped by it. This ensures foreign keys are properly disabled
|
|
158
|
+
before the transaction starts and re-enabled after it commits, preventing
|
|
159
|
+
CASCADE deletes while maintaining data integrity through atomic transactions.
|
|
627
160
|
|
|
628
|
-
*
|
|
161
|
+
*Ruy Rocha*
|
|
629
162
|
|
|
630
|
-
*
|
|
163
|
+
* Add replicas to test database parallelization setup.
|
|
631
164
|
|
|
632
|
-
|
|
633
|
-
Post.with_recursive(
|
|
634
|
-
post_and_replies: [
|
|
635
|
-
Post.where(id: 42),
|
|
636
|
-
Post.joins('JOIN post_and_replies ON posts.in_reply_to_id = post_and_replies.id'),
|
|
637
|
-
]
|
|
638
|
-
)
|
|
639
|
-
```
|
|
165
|
+
Setup and configuration of databases for parallel testing now includes replicas.
|
|
640
166
|
|
|
641
|
-
|
|
167
|
+
This fixes an issue when using a replica database, database selector middleware,
|
|
168
|
+
and non-transactional tests, where integration tests running in parallel would select
|
|
169
|
+
the base test database, i.e. `db_test`, instead of the numbered parallel worker database,
|
|
170
|
+
i.e. `db_test_{n}`.
|
|
642
171
|
|
|
643
|
-
|
|
644
|
-
WITH RECURSIVE "post_and_replies" AS (
|
|
645
|
-
(SELECT "posts".* FROM "posts" WHERE "posts"."id" = 42)
|
|
646
|
-
UNION ALL
|
|
647
|
-
(SELECT "posts".* FROM "posts" JOIN post_and_replies ON posts.in_reply_to_id = post_and_replies.id)
|
|
648
|
-
)
|
|
649
|
-
SELECT "posts".* FROM "posts"
|
|
650
|
-
```
|
|
172
|
+
*Adam Maas*
|
|
651
173
|
|
|
652
|
-
|
|
174
|
+
* Support virtual (not persisted) generated columns on PostgreSQL 18+
|
|
653
175
|
|
|
654
|
-
|
|
176
|
+
PostgreSQL 18 introduces virtual (not persisted) generated columns,
|
|
177
|
+
which are now the default unless the `stored: true` option is explicitly specified on PostgreSQL 18+.
|
|
655
178
|
|
|
656
|
-
ex:
|
|
657
179
|
```ruby
|
|
658
|
-
|
|
659
|
-
t.
|
|
660
|
-
t.
|
|
180
|
+
create_table :users do |t|
|
|
181
|
+
t.string :name
|
|
182
|
+
t.virtual :lower_name, type: :string, as: "LOWER(name)", stored: false
|
|
183
|
+
t.virtual :name_length, type: :integer, as: "LENGTH(name)"
|
|
661
184
|
end
|
|
662
185
|
```
|
|
663
186
|
|
|
664
|
-
*
|
|
665
|
-
|
|
666
|
-
* `PostgreSQLAdapter` now decodes columns of type date to `Date` instead of string.
|
|
187
|
+
*Yasuo Honda*
|
|
667
188
|
|
|
668
|
-
|
|
669
|
-
```ruby
|
|
670
|
-
ActiveRecord::Base.connection
|
|
671
|
-
.select_value("select '2024-01-01'::date").class #=> Date
|
|
672
|
-
```
|
|
189
|
+
* Optimize schema dumping to prevent duplicate file generation.
|
|
673
190
|
|
|
674
|
-
|
|
191
|
+
`ActiveRecord::Tasks::DatabaseTasks.dump_all` now tracks which schema files
|
|
192
|
+
have already been dumped and skips dumping the same file multiple times.
|
|
193
|
+
This improves performance when multiple database configurations share the
|
|
194
|
+
same schema dump path.
|
|
675
195
|
|
|
676
|
-
*
|
|
196
|
+
*Mikey Gough*, *Hartley McGuire*
|
|
677
197
|
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
an N+1 by themselves, calling child associations will no longer raise.
|
|
682
|
-
Fixes #49473.
|
|
198
|
+
* Add structured events for Active Record:
|
|
199
|
+
- `active_record.strict_loading_violation`
|
|
200
|
+
- `active_record.sql`
|
|
683
201
|
|
|
684
|
-
|
|
202
|
+
*Gannon McGibbon*
|
|
685
203
|
|
|
204
|
+
* Add support for integer shard keys.
|
|
686
205
|
```ruby
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
```
|
|
693
|
-
|
|
694
|
-
After:
|
|
206
|
+
# Now accepts symbols as shard keys.
|
|
207
|
+
ActiveRecord::Base.connects_to(shards: {
|
|
208
|
+
1: { writing: :primary_shard_one, reading: :primary_shard_one },
|
|
209
|
+
2: { writing: :primary_shard_two, reading: :primary_shard_two},
|
|
210
|
+
})
|
|
695
211
|
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
person.posts.first # this is 1+1, not N+1
|
|
700
|
-
# SELECT * FROM posts WHERE person_id = 1 ORDER BY id LIMIT 1;
|
|
701
|
-
person.posts.first.firm # no longer raises
|
|
212
|
+
ActiveRecord::Base.connected_to(shard: 1) do
|
|
213
|
+
# ..
|
|
214
|
+
end
|
|
702
215
|
```
|
|
703
216
|
|
|
704
|
-
*
|
|
705
|
-
|
|
706
|
-
* Allow `Sqlite3Adapter` to use `sqlite3` gem version `2.x`.
|
|
707
|
-
|
|
708
|
-
*Mike Dalessio*
|
|
709
|
-
|
|
710
|
-
* Allow `ActiveRecord::Base#pluck` to accept hash values.
|
|
217
|
+
*Nony Dutton*
|
|
711
218
|
|
|
712
|
-
|
|
713
|
-
# Before
|
|
714
|
-
Post.joins(:comments).pluck("posts.id", "comments.id", "comments.body")
|
|
219
|
+
* Add `ActiveRecord::Base.only_columns`
|
|
715
220
|
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
```
|
|
221
|
+
Similar in use case to `ignored_columns` but listing columns to consider rather than the ones
|
|
222
|
+
to ignore.
|
|
719
223
|
|
|
720
|
-
|
|
224
|
+
Can be useful when working with a legacy or shared database schema, or to make safe schema change
|
|
225
|
+
in two deploys rather than three.
|
|
721
226
|
|
|
722
|
-
*
|
|
227
|
+
*Anton Kandratski*
|
|
723
228
|
|
|
724
|
-
|
|
229
|
+
* Use `PG::Connection#close_prepared` (protocol level Close) to deallocate
|
|
230
|
+
prepared statements when available.
|
|
725
231
|
|
|
726
|
-
|
|
232
|
+
To enable its use, you must have pg >= 1.6.0, libpq >= 17, and a PostgreSQL
|
|
233
|
+
database version >= 17.
|
|
727
234
|
|
|
728
|
-
|
|
235
|
+
*Hartley McGuire*, *Andrew Jackson*
|
|
729
236
|
|
|
730
|
-
|
|
731
|
-
Article.transaction do |transaction|
|
|
732
|
-
article.update(published: true)
|
|
733
|
-
transaction.after_commit do
|
|
734
|
-
PublishNotificationMailer.with(article: article).deliver_later
|
|
735
|
-
end
|
|
736
|
-
end
|
|
737
|
-
```
|
|
237
|
+
* Fix query cache for pinned connections in multi threaded transactional tests
|
|
738
238
|
|
|
739
|
-
|
|
239
|
+
When a pinned connection is used across separate threads, they now use a separate cache store
|
|
240
|
+
for each thread.
|
|
740
241
|
|
|
741
|
-
|
|
242
|
+
This improve accuracy of system tests, and any test using multiple threads.
|
|
742
243
|
|
|
743
|
-
|
|
244
|
+
*Heinrich Lee Yu*, *Jean Boussier*
|
|
744
245
|
|
|
745
|
-
|
|
746
|
-
Article.current_transaction.after_commit do
|
|
747
|
-
PublishNotificationMailer.with(article: article).deliver_later
|
|
748
|
-
end
|
|
749
|
-
```
|
|
246
|
+
* Fix time attribute dirty tracking with timezone conversions.
|
|
750
247
|
|
|
751
|
-
|
|
248
|
+
Time-only attributes now maintain a fixed date of 2000-01-01 during timezone conversions,
|
|
249
|
+
preventing them from being incorrectly marked as changed due to date shifts.
|
|
752
250
|
|
|
753
|
-
|
|
251
|
+
This fixes an issue where time attributes would be marked as changed when setting the same time value
|
|
252
|
+
due to timezone conversion causing internal date shifts.
|
|
754
253
|
|
|
755
|
-
|
|
756
|
-
to perform work after the state changes have been properly persisted.
|
|
254
|
+
*Prateek Choudhary*
|
|
757
255
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
ActiveRecord.after_all_transactions_commit do
|
|
762
|
-
PublishNotificationMailer.with(article: article).deliver_later
|
|
763
|
-
end
|
|
764
|
-
end
|
|
765
|
-
```
|
|
256
|
+
* Skip calling `PG::Connection#cancel` in `cancel_any_running_query`
|
|
257
|
+
when using libpq >= 18 with pg < 1.6.0, due to incompatibility.
|
|
258
|
+
Rollback still runs, but may take longer.
|
|
766
259
|
|
|
767
|
-
|
|
768
|
-
of a transaction, or called after the open transaction is committed.
|
|
260
|
+
*Yasuo Honda*, *Lars Kanis*
|
|
769
261
|
|
|
770
|
-
|
|
262
|
+
* Don't add `id_value` attribute alias when attribute/column with that name already exists.
|
|
771
263
|
|
|
772
|
-
*
|
|
264
|
+
*Rob Lewis*
|
|
773
265
|
|
|
774
|
-
*
|
|
266
|
+
* Remove deprecated `:unsigned_float` and `:unsigned_decimal` column methods for MySQL.
|
|
775
267
|
|
|
776
|
-
|
|
777
|
-
values must be backfilled separately of the column addition (to not lock the table for too long)
|
|
778
|
-
and before the use of `:counter_cache` (otherwise methods like `size`/`any?`/etc, which use
|
|
779
|
-
counter caches internally, can produce incorrect results). People usually use database triggers
|
|
780
|
-
or callbacks on child associations while backfilling before introducing a counter cache
|
|
781
|
-
configuration to the association.
|
|
268
|
+
*Rafael Mendonça França*
|
|
782
269
|
|
|
783
|
-
|
|
270
|
+
* Remove deprecated `:retries` option for the SQLite3 adapter.
|
|
784
271
|
|
|
785
|
-
|
|
786
|
-
class Comment < ApplicationRecord
|
|
787
|
-
belongs_to :post, counter_cache: { active: false }
|
|
788
|
-
end
|
|
789
|
-
```
|
|
272
|
+
*Rafael Mendonça França*
|
|
790
273
|
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
remove the `{ active: false }` part from the counter cache definition, and it will now be used by the
|
|
794
|
-
mentioned methods.
|
|
274
|
+
* Introduce new database configuration options `keepalive`, `max_age`, and
|
|
275
|
+
`min_connections` -- and rename `pool` to `max_connections` to match.
|
|
795
276
|
|
|
796
|
-
|
|
277
|
+
There are no changes to default behavior, but these allow for more specific
|
|
278
|
+
control over pool behavior.
|
|
797
279
|
|
|
798
|
-
*
|
|
280
|
+
*Matthew Draper*, *Chris AtLee*, *Rachael Wright-Munn*
|
|
799
281
|
|
|
800
|
-
|
|
801
|
-
are idempotent and can safely be retried in the case of a connection error. Previously,
|
|
802
|
-
adapters such as `TrilogyAdapter` would raise `ActiveRecord::ConnectionFailed: Trilogy::EOFError`
|
|
803
|
-
when encountering a connection error mid-request.
|
|
282
|
+
* Move `LIMIT` validation from query generation to when `limit()` is called.
|
|
804
283
|
|
|
805
|
-
*
|
|
284
|
+
*Hartley McGuire*, *Shuyang*
|
|
806
285
|
|
|
807
|
-
*
|
|
286
|
+
* Add `ActiveRecord::CheckViolation` error class for check constraint violations.
|
|
808
287
|
|
|
809
|
-
|
|
810
|
-
Now it's possible to pass an Array value as `foreign_key` to achieve the same behavior of an association.
|
|
288
|
+
*Ryuta Kamizono*
|
|
811
289
|
|
|
812
|
-
|
|
290
|
+
* Add `ActiveRecord::ExclusionViolation` error class for exclusion constraint violations.
|
|
813
291
|
|
|
814
|
-
|
|
292
|
+
When an exclusion constraint is violated in PostgreSQL, the error will now be raised
|
|
293
|
+
as `ActiveRecord::ExclusionViolation` instead of the generic `ActiveRecord::StatementInvalid`,
|
|
294
|
+
making it easier to handle these specific constraint violations in application code.
|
|
815
295
|
|
|
816
|
-
|
|
817
|
-
|
|
296
|
+
This follows the same pattern as other constraint violation error classes like
|
|
297
|
+
`RecordNotUnique` for unique constraint violations and `InvalidForeignKey` for
|
|
298
|
+
foreign key constraint violations.
|
|
818
299
|
|
|
819
|
-
*
|
|
300
|
+
*Ryuta Kamizono*
|
|
820
301
|
|
|
821
|
-
*
|
|
302
|
+
* Attributes filtered by `filter_attributes` will now also be filtered by `filter_parameters`
|
|
303
|
+
so sensitive information is not leaked.
|
|
822
304
|
|
|
823
|
-
|
|
305
|
+
*Jill Klang*
|
|
824
306
|
|
|
825
|
-
|
|
826
|
-
the request or job. This behavior can be undesirable in environments that use many more threads or fibers than there
|
|
827
|
-
is available connections.
|
|
307
|
+
* Add `connection.current_transaction.isolation` API to check current transaction's isolation level.
|
|
828
308
|
|
|
829
|
-
|
|
830
|
-
|
|
309
|
+
Returns the isolation level if it was explicitly set via the `isolation:` parameter
|
|
310
|
+
or through `ActiveRecord.with_transaction_isolation_level`, otherwise returns `nil`.
|
|
311
|
+
Nested transactions return the parent transaction's isolation level.
|
|
831
312
|
|
|
832
|
-
|
|
313
|
+
```ruby
|
|
314
|
+
# Returns nil when no transaction
|
|
315
|
+
User.connection.current_transaction.isolation # => nil
|
|
833
316
|
|
|
834
|
-
|
|
317
|
+
# Returns explicitly set isolation level
|
|
318
|
+
User.transaction(isolation: :serializable) do
|
|
319
|
+
User.connection.current_transaction.isolation # => :serializable
|
|
320
|
+
end
|
|
835
321
|
|
|
836
|
-
|
|
322
|
+
# Returns nil when isolation not explicitly set
|
|
323
|
+
User.transaction do
|
|
324
|
+
User.connection.current_transaction.isolation # => nil
|
|
325
|
+
end
|
|
837
326
|
|
|
838
|
-
|
|
839
|
-
|
|
327
|
+
# Nested transactions inherit parent's isolation
|
|
328
|
+
User.transaction(isolation: :read_committed) do
|
|
329
|
+
User.transaction do
|
|
330
|
+
User.connection.current_transaction.isolation # => :read_committed
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
```
|
|
840
334
|
|
|
841
|
-
|
|
842
|
-
When set to `false`, writes to the affected connection pool will not clear any query cache.
|
|
335
|
+
*Kir Shatrov*
|
|
843
336
|
|
|
844
|
-
|
|
337
|
+
* Fix `#merge` with `#or` or `#and` and a mixture of attributes and SQL strings resulting in an incorrect query.
|
|
845
338
|
|
|
846
|
-
|
|
339
|
+
```ruby
|
|
340
|
+
base = Comment.joins(:post).where(user_id: 1).where("recent = 1")
|
|
341
|
+
puts base.merge(base.where(draft: true).or(Post.where(archived: true))).to_sql
|
|
342
|
+
```
|
|
847
343
|
|
|
848
|
-
|
|
344
|
+
Before:
|
|
849
345
|
|
|
850
|
-
|
|
851
|
-
|
|
346
|
+
```SQL
|
|
347
|
+
SELECT "comments".* FROM "comments"
|
|
348
|
+
INNER JOIN "posts" ON "posts"."id" = "comments"."post_id"
|
|
349
|
+
WHERE (recent = 1)
|
|
350
|
+
AND (
|
|
351
|
+
"comments"."user_id" = 1
|
|
352
|
+
AND (recent = 1)
|
|
353
|
+
AND "comments"."draft" = 1
|
|
354
|
+
OR "posts"."archived" = 1
|
|
355
|
+
)
|
|
356
|
+
```
|
|
852
357
|
|
|
853
|
-
|
|
854
|
-
current plan to remove the method.
|
|
358
|
+
After:
|
|
855
359
|
|
|
856
|
-
|
|
360
|
+
```SQL
|
|
361
|
+
SELECT "comments".* FROM "comments"
|
|
362
|
+
INNER JOIN "posts" ON "posts"."id" = "comments"."post_id"
|
|
363
|
+
WHERE "comments"."user_id" = 1
|
|
364
|
+
AND (recent = 1)
|
|
365
|
+
AND (
|
|
366
|
+
"comments"."user_id" = 1
|
|
367
|
+
AND (recent = 1)
|
|
368
|
+
AND "comments"."draft" = 1
|
|
369
|
+
OR "posts"."archived" = 1
|
|
370
|
+
)
|
|
371
|
+
```
|
|
857
372
|
|
|
858
|
-
*
|
|
373
|
+
*Joshua Young*
|
|
859
374
|
|
|
860
|
-
|
|
861
|
-
connection will be held for the duration of the request or job.
|
|
375
|
+
* Make schema dumper to account for `ActiveRecord.dump_schemas` when dumping in `:ruby` format.
|
|
862
376
|
|
|
863
|
-
*
|
|
377
|
+
*fatkodima*
|
|
864
378
|
|
|
865
|
-
*
|
|
379
|
+
* Add `:touch` option to `update_column`/`update_columns` methods.
|
|
866
380
|
|
|
867
381
|
```ruby
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
```
|
|
382
|
+
# Will update :updated_at/:updated_on alongside :nice column.
|
|
383
|
+
user.update_column(:nice, true, touch: true)
|
|
871
384
|
|
|
872
|
-
|
|
385
|
+
# Will update :updated_at/:updated_on alongside :last_ip column
|
|
386
|
+
user.update_columns(last_ip: request.remote_ip, touch: true)
|
|
387
|
+
```
|
|
873
388
|
|
|
874
|
-
*
|
|
875
|
-
incorrect error message.
|
|
389
|
+
*Dmitrii Ivliev*
|
|
876
390
|
|
|
877
|
-
|
|
391
|
+
* Optimize Active Record batching further when using ranges.
|
|
878
392
|
|
|
879
|
-
|
|
393
|
+
Tested on a PostgreSQL table with 10M records and batches of 10k records, the generation
|
|
394
|
+
of relations for the 1000 batches was `4.8x` faster (`6.8s` vs. `1.4s`), used `900x`
|
|
395
|
+
less bandwidth (`180MB` vs. `0.2MB`) and allocated `45x` less memory (`490MB` vs. `11MB`).
|
|
880
396
|
|
|
881
|
-
*
|
|
397
|
+
*Maxime Réty*, *fatkodima*
|
|
882
398
|
|
|
883
|
-
|
|
884
|
-
an `ActiveRecord::ReadonlyAttributeError` when the foreign key attribute is marked as read-only.
|
|
399
|
+
* Include current character length in error messages for index and table name length validations.
|
|
885
400
|
|
|
886
401
|
*Joshua Young*
|
|
887
402
|
|
|
888
|
-
*
|
|
403
|
+
* Add `rename_schema` method for PostgreSQL.
|
|
889
404
|
|
|
890
|
-
*
|
|
405
|
+
*T S Vallender*
|
|
891
406
|
|
|
892
|
-
*
|
|
407
|
+
* Implement support for deprecating associations:
|
|
893
408
|
|
|
894
|
-
|
|
409
|
+
```ruby
|
|
410
|
+
has_many :posts, deprecated: true
|
|
411
|
+
```
|
|
895
412
|
|
|
896
|
-
|
|
413
|
+
With that, Active Record will report any usage of the `posts` association.
|
|
897
414
|
|
|
898
|
-
|
|
415
|
+
Three reporting modes are supported (`:warn`, `:raise`, and `:notify`), and
|
|
416
|
+
backtraces can be enabled or disabled. Defaults are `:warn` mode and
|
|
417
|
+
disabled backtraces.
|
|
899
418
|
|
|
900
|
-
|
|
419
|
+
Please, check the docs for further details.
|
|
901
420
|
|
|
902
|
-
*
|
|
421
|
+
*Xavier Noria*
|
|
903
422
|
|
|
904
|
-
*
|
|
423
|
+
* PostgreSQL adapter create DB now supports `locale_provider` and `locale`.
|
|
905
424
|
|
|
906
|
-
*
|
|
425
|
+
*Bengt-Ove Hollaender*
|
|
907
426
|
|
|
908
|
-
*
|
|
427
|
+
* Use ntuples to populate row_count instead of count for Postgres
|
|
909
428
|
|
|
910
|
-
*
|
|
429
|
+
*Jonathan Calvert*
|
|
911
430
|
|
|
912
|
-
*
|
|
431
|
+
* Fix checking whether an unpersisted record is `include?`d in a strictly
|
|
432
|
+
loaded `has_and_belongs_to_many` association.
|
|
913
433
|
|
|
914
|
-
*
|
|
434
|
+
*Hartley McGuire*
|
|
915
435
|
|
|
916
|
-
*
|
|
917
|
-
`#clear_reloadable_connections!`, `#clear_all_connections!` and `#flush_idle_connections!` to the connections pools
|
|
918
|
-
for the current role when the `role` argument isn't provided.
|
|
436
|
+
* Add ability to change transaction isolation for all pools within a block.
|
|
919
437
|
|
|
920
|
-
|
|
438
|
+
This functionality is useful if your application needs to change the database
|
|
439
|
+
transaction isolation for a request or action.
|
|
921
440
|
|
|
922
|
-
|
|
441
|
+
Calling `ActiveRecord.with_transaction_isolation_level(level) {}` in an around filter or
|
|
442
|
+
middleware will set the transaction isolation for all pools accessed within the block,
|
|
443
|
+
but not for the pools that aren't.
|
|
923
444
|
|
|
924
|
-
|
|
445
|
+
This works with explicit and implicit transactions:
|
|
925
446
|
|
|
926
|
-
|
|
447
|
+
```ruby
|
|
448
|
+
ActiveRecord.with_transaction_isolation_level(:read_committed) do
|
|
449
|
+
Tag.transaction do # opens a transaction explicitly
|
|
450
|
+
Tag.create!
|
|
451
|
+
end
|
|
452
|
+
end
|
|
453
|
+
```
|
|
927
454
|
|
|
928
|
-
|
|
455
|
+
```ruby
|
|
456
|
+
ActiveRecord.with_transaction_isolation_level(:read_committed) do
|
|
457
|
+
Tag.create! # opens a transaction implicitly
|
|
458
|
+
end
|
|
459
|
+
```
|
|
929
460
|
|
|
930
|
-
*
|
|
461
|
+
*Eileen M. Uchitelle*
|
|
931
462
|
|
|
932
|
-
|
|
463
|
+
* Raise `ActiveRecord::MissingRequiredOrderError` when order dependent finder methods (e.g. `#first`, `#last`) are
|
|
464
|
+
called without `order` values on the relation, and the model does not have any order columns (`implicit_order_column`,
|
|
465
|
+
`query_constraints`, or `primary_key`) to fall back on.
|
|
933
466
|
|
|
934
|
-
|
|
467
|
+
This change will be introduced with a new framework default for Rails 8.1, and the current behavior of not raising
|
|
468
|
+
an error has been deprecated with the aim of removing the configuration option in Rails 8.2.
|
|
935
469
|
|
|
936
|
-
|
|
470
|
+
```ruby
|
|
471
|
+
config.active_record.raise_on_missing_required_finder_order_columns = true
|
|
472
|
+
```
|
|
937
473
|
|
|
938
|
-
*
|
|
474
|
+
*Joshua Young*
|
|
939
475
|
|
|
940
|
-
|
|
476
|
+
* `:class_name` is now invalid in polymorphic `belongs_to` associations.
|
|
941
477
|
|
|
942
|
-
|
|
478
|
+
Reason is `:class_name` does not make sense in those associations because
|
|
479
|
+
the class name of target records is dynamic and stored in the type column.
|
|
943
480
|
|
|
944
|
-
|
|
481
|
+
Existing polymorphic associations setting this option can just delete it.
|
|
482
|
+
While it did not raise, it had no effect anyway.
|
|
945
483
|
|
|
946
|
-
*
|
|
484
|
+
*Xavier Noria*
|
|
947
485
|
|
|
948
|
-
|
|
486
|
+
* Add support for multiple databases to `db:migrate:reset`.
|
|
949
487
|
|
|
950
|
-
*
|
|
488
|
+
*Joé Dupuis*
|
|
951
489
|
|
|
952
|
-
|
|
490
|
+
* Add `affected_rows` to `ActiveRecord::Result`.
|
|
953
491
|
|
|
954
|
-
*
|
|
492
|
+
*Jenny Shen*
|
|
955
493
|
|
|
956
|
-
|
|
494
|
+
* Enable passing retryable SqlLiterals to `#where`.
|
|
957
495
|
|
|
958
|
-
*
|
|
959
|
-
`ActiveRecord::MigrationContext`.
|
|
496
|
+
*Hartley McGuire*
|
|
960
497
|
|
|
961
|
-
|
|
498
|
+
* Set default for primary keys in `insert_all`/`upsert_all`.
|
|
962
499
|
|
|
963
|
-
|
|
500
|
+
Previously in Postgres, updating and inserting new records in one upsert wasn't possible
|
|
501
|
+
due to null primary key values. `nil` primary key values passed into `insert_all`/`upsert_all`
|
|
502
|
+
are now implicitly set to the default insert value specified by adapter.
|
|
964
503
|
|
|
965
|
-
*
|
|
504
|
+
*Jenny Shen*
|
|
966
505
|
|
|
967
|
-
*
|
|
506
|
+
* Add a load hook `active_record_database_configurations` for `ActiveRecord::DatabaseConfigurations`
|
|
968
507
|
|
|
969
|
-
*
|
|
508
|
+
*Mike Dalessio*
|
|
970
509
|
|
|
971
|
-
*
|
|
510
|
+
* Use `TRUE` and `FALSE` for SQLite queries with boolean columns.
|
|
972
511
|
|
|
973
|
-
*
|
|
512
|
+
*Hartley McGuire*
|
|
974
513
|
|
|
975
|
-
*
|
|
514
|
+
* Bump minimum supported SQLite to 3.23.0.
|
|
976
515
|
|
|
977
|
-
*
|
|
516
|
+
*Hartley McGuire*
|
|
978
517
|
|
|
979
|
-
*
|
|
518
|
+
* Allow allocated Active Records to lookup associations.
|
|
980
519
|
|
|
981
|
-
|
|
520
|
+
Previously, the association cache isn't setup on allocated record objects, so association
|
|
521
|
+
lookups will crash. Test frameworks like mocha use allocate to check for stubbable instance
|
|
522
|
+
methods, which can trigger an association lookup.
|
|
982
523
|
|
|
983
|
-
*
|
|
524
|
+
*Gannon McGibbon*
|
|
984
525
|
|
|
985
|
-
|
|
526
|
+
* Encryption now supports `support_unencrypted_data: true` being set per-attribute.
|
|
986
527
|
|
|
987
|
-
|
|
528
|
+
Previously this only worked if `ActiveRecord::Encryption.config.support_unencrypted_data == true`.
|
|
529
|
+
Now, if the global config is turned off, you can still opt in for a specific attribute.
|
|
988
530
|
|
|
989
|
-
|
|
531
|
+
```ruby
|
|
532
|
+
# ActiveRecord::Encryption.config.support_unencrypted_data = true
|
|
533
|
+
class User < ActiveRecord::Base
|
|
534
|
+
encrypts :name, support_unencrypted_data: false # only supports encrypted data
|
|
535
|
+
encrypts :email # supports encrypted or unencrypted data
|
|
536
|
+
end
|
|
537
|
+
```
|
|
990
538
|
|
|
991
|
-
|
|
539
|
+
```ruby
|
|
540
|
+
# ActiveRecord::Encryption.config.support_unencrypted_data = false
|
|
541
|
+
class User < ActiveRecord::Base
|
|
542
|
+
encrypts :name, support_unencrypted_data: true # supports encrypted or unencrypted data
|
|
543
|
+
encrypts :email # only supports encrypted data
|
|
544
|
+
end
|
|
545
|
+
```
|
|
992
546
|
|
|
993
|
-
*
|
|
547
|
+
*Alex Ghiculescu*
|
|
994
548
|
|
|
995
|
-
*
|
|
549
|
+
* Model generator no longer needs a database connection to validate column types.
|
|
996
550
|
|
|
997
|
-
*
|
|
551
|
+
*Mike Dalessio*
|
|
998
552
|
|
|
999
|
-
*
|
|
553
|
+
* Allow signed ID verifiers to be configurable via `Rails.application.message_verifiers`
|
|
1000
554
|
|
|
1001
|
-
|
|
555
|
+
Prior to this change, the primary way to configure signed ID verifiers was
|
|
556
|
+
to set `signed_id_verifier` on each model class:
|
|
1002
557
|
|
|
1003
|
-
|
|
558
|
+
```ruby
|
|
559
|
+
Post.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
|
|
560
|
+
Comment.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
|
|
561
|
+
```
|
|
1004
562
|
|
|
1005
|
-
|
|
563
|
+
And if the developer did not set `signed_id_verifier`, a verifier would be
|
|
564
|
+
instantiated with a secret derived from `secret_key_base` and the following
|
|
565
|
+
options:
|
|
1006
566
|
|
|
1007
|
-
|
|
567
|
+
```ruby
|
|
568
|
+
{ digest: "SHA256", serializer: JSON, url_safe: true }
|
|
569
|
+
```
|
|
1008
570
|
|
|
1009
|
-
|
|
571
|
+
Thus it was cumbersome to rotate configuration for all verifiers.
|
|
1010
572
|
|
|
1011
|
-
|
|
573
|
+
This change defines a new Rails config: [`config.active_record.use_legacy_signed_id_verifier`][].
|
|
574
|
+
The default value is `:generate_and_verify`, which preserves the previous
|
|
575
|
+
behavior. However, when set to `:verify`, signed ID verifiers will use
|
|
576
|
+
configuration from `Rails.application.message_verifiers` (specifically,
|
|
577
|
+
`Rails.application.message_verifiers["active_record/signed_id"]`) to
|
|
578
|
+
generate and verify signed IDs, but will also verify signed IDs using the
|
|
579
|
+
older configuration.
|
|
1012
580
|
|
|
1013
|
-
|
|
581
|
+
To avoid complication, the new behavior only applies when `signed_id_verifier_secret`
|
|
582
|
+
is not set on a model class or any of its ancestors. Additionally,
|
|
583
|
+
`signed_id_verifier_secret` is now deprecated. If you are currently setting
|
|
584
|
+
`signed_id_verifier_secret` on a model class, you can set `signed_id_verifier`
|
|
585
|
+
instead:
|
|
1014
586
|
|
|
1015
|
-
|
|
587
|
+
```ruby
|
|
588
|
+
# BEFORE
|
|
589
|
+
Post.signed_id_verifier_secret = "my secret"
|
|
1016
590
|
|
|
1017
|
-
|
|
591
|
+
# AFTER
|
|
592
|
+
Post.signed_id_verifier = ActiveSupport::MessageVerifier.new("my secret", digest: "SHA256", serializer: JSON, url_safe: true)
|
|
593
|
+
```
|
|
1018
594
|
|
|
1019
|
-
|
|
1020
|
-
|
|
595
|
+
To ease migration, `signed_id_verifier` has also been changed to behave as a
|
|
596
|
+
`class_attribute` (i.e. inheritable), but _only when `signed_id_verifier_secret`
|
|
597
|
+
is not set_:
|
|
1021
598
|
|
|
1022
|
-
|
|
599
|
+
```ruby
|
|
600
|
+
# BEFORE
|
|
601
|
+
ActiveRecord::Base.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
|
|
602
|
+
Post.signed_id_verifier == ActiveRecord::Base.signed_id_verifier # => false
|
|
1023
603
|
|
|
1024
|
-
|
|
604
|
+
# AFTER
|
|
605
|
+
ActiveRecord::Base.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
|
|
606
|
+
Post.signed_id_verifier == ActiveRecord::Base.signed_id_verifier # => true
|
|
1025
607
|
|
|
1026
|
-
|
|
608
|
+
Post.signed_id_verifier_secret = "my secret" # => deprecation warning
|
|
609
|
+
Post.signed_id_verifier == ActiveRecord::Base.signed_id_verifier # => false
|
|
610
|
+
```
|
|
1027
611
|
|
|
1028
|
-
|
|
1029
|
-
|
|
612
|
+
Note, however, that it is recommended to eventually migrate from
|
|
613
|
+
model-specific verifiers to a unified configuration managed by
|
|
614
|
+
`Rails.application.message_verifiers`. `ActiveSupport::MessageVerifier#rotate`
|
|
615
|
+
can facilitate that transition. For example:
|
|
1030
616
|
|
|
1031
|
-
|
|
617
|
+
```ruby
|
|
618
|
+
# BEFORE
|
|
619
|
+
# Generate and verify signed Post IDs using Post-specific configuration
|
|
620
|
+
Post.signed_id_verifier = ActiveSupport::MessageVerifier.new("post secret", ...)
|
|
1032
621
|
|
|
1033
|
-
|
|
622
|
+
# AFTER
|
|
623
|
+
# Generate and verify signed Post IDs using the unified configuration
|
|
624
|
+
Post.signed_id_verifier = Post.signed_id_verifier.dup
|
|
625
|
+
# Fall back to Post-specific configuration when verifying signed IDs
|
|
626
|
+
Post.signed_id_verifier.rotate("post secret", ...)
|
|
627
|
+
```
|
|
1034
628
|
|
|
1035
|
-
|
|
629
|
+
[`config.active_record.use_legacy_signed_id_verifier`]: https://guides.rubyonrails.org/v8.1/configuring.html#config-active-record-use-legacy-signed-id-verifier
|
|
1036
630
|
|
|
1037
|
-
*
|
|
631
|
+
*Ali Sepehri*, *Jonathan Hefner*
|
|
1038
632
|
|
|
1039
|
-
|
|
1040
|
-
will yield that same connection.
|
|
633
|
+
* Prepend `extra_flags` in postgres' `structure_load`
|
|
1041
634
|
|
|
1042
|
-
|
|
1043
|
-
|
|
635
|
+
When specifying `structure_load_flags` with a postgres adapter, the flags
|
|
636
|
+
were appended to the default flags, instead of prepended.
|
|
637
|
+
This caused issues with flags not being taken into account by postgres.
|
|
1044
638
|
|
|
1045
|
-
*
|
|
639
|
+
*Alice Loeser*
|
|
1046
640
|
|
|
1047
|
-
*
|
|
1048
|
-
notification includes `:row_count` field.
|
|
641
|
+
* Allow bypassing primary key/constraint addition in `implicit_order_column`
|
|
1049
642
|
|
|
1050
|
-
|
|
643
|
+
When specifying multiple columns in an array for `implicit_order_column`, adding
|
|
644
|
+
`nil` as the last element will prevent appending the primary key to order
|
|
645
|
+
conditions. This allows more precise control of indexes used by
|
|
646
|
+
generated queries. It should be noted that this feature does introduce the risk
|
|
647
|
+
of API misbehavior if the specified columns are not fully unique.
|
|
1051
648
|
|
|
1052
|
-
*
|
|
649
|
+
*Issy Long*
|
|
1053
650
|
|
|
1054
|
-
|
|
651
|
+
* Allow setting the `schema_format` via database configuration.
|
|
1055
652
|
|
|
1056
|
-
```ruby
|
|
1057
|
-
Post.left_joins(:author).where.associated(:author)
|
|
1058
653
|
```
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
*Saleh Alhaddad*
|
|
1063
|
-
|
|
1064
|
-
* Fix an issue where `ActiveRecord::Encryption` configurations are not ready before the loading
|
|
1065
|
-
of Active Record models, when an application is eager loaded. As a result, encrypted attributes
|
|
1066
|
-
could be misconfigured in some cases.
|
|
1067
|
-
|
|
1068
|
-
*Maxime Réty*
|
|
1069
|
-
|
|
1070
|
-
* Deprecate defining an `enum` with keyword arguments.
|
|
1071
|
-
|
|
1072
|
-
```ruby
|
|
1073
|
-
class Function > ApplicationRecord
|
|
1074
|
-
# BAD
|
|
1075
|
-
enum color: [:red, :blue],
|
|
1076
|
-
type: [:instance, :class]
|
|
1077
|
-
|
|
1078
|
-
# GOOD
|
|
1079
|
-
enum :color, [:red, :blue]
|
|
1080
|
-
enum :type, [:instance, :class]
|
|
1081
|
-
end
|
|
654
|
+
primary:
|
|
655
|
+
schema_format: ruby
|
|
1082
656
|
```
|
|
1083
657
|
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
* Add `config.active_record.validate_migration_timestamps` option for validating migration timestamps.
|
|
658
|
+
Useful for multi-database setups when apps require different formats per-database.
|
|
1087
659
|
|
|
1088
|
-
|
|
1089
|
-
the timestamp associated with the current time. This is designed to prevent migrations prefixes
|
|
1090
|
-
from being hand-edited to future timestamps, which impacts migration generation and other
|
|
1091
|
-
migration commands.
|
|
660
|
+
*T S Vallender*
|
|
1092
661
|
|
|
1093
|
-
|
|
662
|
+
* Support disabling indexes for MySQL v8.0.0+ and MariaDB v10.6.0+
|
|
1094
663
|
|
|
1095
|
-
|
|
664
|
+
MySQL 8.0.0 added an option to disable indexes from being used by the query
|
|
665
|
+
optimizer by making them "invisible". This allows the index to still be maintained
|
|
666
|
+
and updated but no queries will be permitted to use it. This can be useful for adding
|
|
667
|
+
new invisible indexes or making existing indexes invisible before dropping them
|
|
668
|
+
to ensure queries are not negatively affected.
|
|
669
|
+
See https://dev.mysql.com/blog-archive/mysql-8-0-invisible-indexes/ for more details.
|
|
1096
670
|
|
|
1097
|
-
|
|
671
|
+
MariaDB 10.6.0 also added support for this feature by allowing indexes to be "ignored"
|
|
672
|
+
in queries. See https://mariadb.com/kb/en/ignored-indexes/ for more details.
|
|
1098
673
|
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
and
|
|
674
|
+
Active Record now supports this option for MySQL 8.0.0+ and MariaDB 10.6.0+ for
|
|
675
|
+
index creation and alteration where the new index option `enabled: true/false` can be
|
|
676
|
+
passed to column and index methods as below:
|
|
1102
677
|
|
|
1103
|
-
|
|
678
|
+
```ruby
|
|
679
|
+
add_index :users, :email, enabled: false
|
|
680
|
+
enable_index :users, :email
|
|
681
|
+
add_column :users, :dob, :string, index: { enabled: false }
|
|
1104
682
|
|
|
1105
|
-
|
|
683
|
+
change_table :users do |t|
|
|
684
|
+
t.index :name, enabled: false
|
|
685
|
+
t.index :dob
|
|
686
|
+
t.disable_index :dob
|
|
687
|
+
t.column :username, :string, index: { enabled: false }
|
|
688
|
+
t.references :account, index: { enabled: false }
|
|
689
|
+
end
|
|
1106
690
|
|
|
1107
|
-
|
|
1108
|
-
|
|
691
|
+
create_table :users do |t|
|
|
692
|
+
t.string :name, index: { enabled: false }
|
|
693
|
+
t.string :email
|
|
694
|
+
t.index :email, enabled: false
|
|
695
|
+
end
|
|
1109
696
|
```
|
|
1110
697
|
|
|
1111
|
-
|
|
1112
|
-
(note, there is also a `config.active_record.verbose_query_logs` that serves the same purpose)
|
|
1113
|
-
or occasionally on production for debugging purposes.
|
|
698
|
+
*Merve Taner*
|
|
1114
699
|
|
|
1115
|
-
|
|
700
|
+
* Respect `implicit_order_column` in `ActiveRecord::Relation#reverse_order`.
|
|
1116
701
|
|
|
1117
|
-
*
|
|
702
|
+
*Joshua Young*
|
|
1118
703
|
|
|
1119
|
-
|
|
704
|
+
* Add column types to `ActiveRecord::Result` for SQLite3.
|
|
1120
705
|
|
|
1121
|
-
|
|
1122
|
-
class User
|
|
1123
|
-
encrypts :name, encryptor: ActiveRecord::Encryption::Encryptor.new(compress: false)
|
|
1124
|
-
end
|
|
1125
|
-
```
|
|
706
|
+
*Andrew Kane*
|
|
1126
707
|
|
|
1127
|
-
|
|
708
|
+
* Raise `ActiveRecord::ReadOnlyError` when pessimistically locking with a readonly role.
|
|
1128
709
|
|
|
1129
|
-
*
|
|
710
|
+
*Joshua Young*
|
|
1130
711
|
|
|
1131
|
-
|
|
712
|
+
* Fix using the `SQLite3Adapter`'s `dbconsole` method outside of a Rails application.
|
|
1132
713
|
|
|
1133
|
-
*
|
|
714
|
+
*Hartley McGuire*
|
|
1134
715
|
|
|
1135
|
-
*
|
|
716
|
+
* Fix migrating multiple databases with `ActiveRecord::PendingMigration` action.
|
|
1136
717
|
|
|
1137
|
-
|
|
718
|
+
*Gannon McGibbon*
|
|
1138
719
|
|
|
1139
|
-
|
|
720
|
+
* Enable automatically retrying idempotent association queries on connection
|
|
721
|
+
errors.
|
|
1140
722
|
|
|
1141
|
-
*
|
|
723
|
+
*Hartley McGuire*
|
|
724
|
+
|
|
725
|
+
* Add `allow_retry` to `sql.active_record` instrumentation.
|
|
1142
726
|
|
|
1143
|
-
|
|
727
|
+
This enables identifying queries which queries are automatically retryable on connection errors.
|
|
1144
728
|
|
|
1145
|
-
|
|
729
|
+
*Hartley McGuire*
|
|
1146
730
|
|
|
1147
|
-
|
|
731
|
+
* Better support UPDATE with JOIN for Postgresql and SQLite3
|
|
1148
732
|
|
|
1149
|
-
|
|
733
|
+
Previously when generating update queries with one or more JOIN clauses,
|
|
734
|
+
Active Record would use a sub query which would prevent to reference the joined
|
|
735
|
+
tables in the `SET` clause, for instance:
|
|
1150
736
|
|
|
1151
|
-
|
|
737
|
+
```ruby
|
|
738
|
+
Comment.joins(:post).update_all("title = posts.title")
|
|
739
|
+
```
|
|
1152
740
|
|
|
1153
|
-
|
|
741
|
+
This is now supported as long as the relation doesn't also use a `LIMIT`, `ORDER` or
|
|
742
|
+
`GROUP BY` clause. This was supported by the MySQL adapter for a long time.
|
|
1154
743
|
|
|
1155
|
-
|
|
744
|
+
*Jean Boussier*
|
|
1156
745
|
|
|
1157
|
-
|
|
746
|
+
* Introduce a before-fork hook in `ActiveSupport::Testing::Parallelization` to clear existing
|
|
747
|
+
connections, to avoid fork-safety issues with the mysql2 adapter.
|
|
1158
748
|
|
|
1159
|
-
|
|
749
|
+
Fixes #41776
|
|
1160
750
|
|
|
1161
|
-
*
|
|
751
|
+
*Mike Dalessio*, *Donal McBreen*
|
|
1162
752
|
|
|
1163
|
-
*
|
|
1164
|
-
`add_reference` and `t.references`.
|
|
753
|
+
* PoolConfig no longer keeps a reference to the connection class.
|
|
1165
754
|
|
|
1166
|
-
|
|
755
|
+
Keeping a reference to the class caused subtle issues when combined with reloading in
|
|
756
|
+
development. Fixes #54343.
|
|
1167
757
|
|
|
1168
|
-
*
|
|
758
|
+
*Mike Dalessio*
|
|
1169
759
|
|
|
1170
|
-
|
|
760
|
+
* Fix SQL notifications sometimes not sent when using async queries.
|
|
1171
761
|
|
|
1172
|
-
|
|
762
|
+
```ruby
|
|
763
|
+
Post.async_count
|
|
764
|
+
ActiveSupport::Notifications.subscribed(->(*) { "Will never reach here" }) do
|
|
765
|
+
Post.count
|
|
766
|
+
end
|
|
767
|
+
```
|
|
1173
768
|
|
|
1174
|
-
|
|
769
|
+
In rare circumstances and under the right race condition, Active Support notifications
|
|
770
|
+
would no longer be dispatched after using an asynchronous query.
|
|
771
|
+
This is now fixed.
|
|
1175
772
|
|
|
1176
|
-
|
|
1177
|
-
cache.
|
|
773
|
+
*Edouard Chin*
|
|
1178
774
|
|
|
1179
|
-
|
|
775
|
+
* Eliminate queries loading dumped schema cache on Postgres
|
|
1180
776
|
|
|
1181
|
-
|
|
777
|
+
Improve resiliency by avoiding needing to open a database connection to load the
|
|
778
|
+
type map while defining attribute methods at boot when a schema cache file is
|
|
779
|
+
configured on PostgreSQL databases.
|
|
1182
780
|
|
|
1183
|
-
|
|
1184
|
-
but with support for `after_commit` and `after_rollback` callback options.
|
|
781
|
+
*James Coleman*
|
|
1185
782
|
|
|
1186
|
-
|
|
783
|
+
* `ActiveRecord::Coder::JSON` can be instantiated
|
|
1187
784
|
|
|
1188
|
-
|
|
785
|
+
Options can now be passed to `ActiveRecord::Coder::JSON` when instantiating the coder. This allows:
|
|
786
|
+
```ruby
|
|
787
|
+
serialize :config, coder: ActiveRecord::Coder::JSON.new(symbolize_names: true)
|
|
788
|
+
```
|
|
789
|
+
*matthaigh27*
|
|
1189
790
|
|
|
1190
|
-
|
|
791
|
+
* Deprecate using `insert_all`/`upsert_all` with unpersisted records in associations.
|
|
1191
792
|
|
|
1192
|
-
|
|
793
|
+
Using these methods on associations containing unpersisted records will now
|
|
794
|
+
show a deprecation warning, as the unpersisted records will be lost after
|
|
795
|
+
the operation.
|
|
1193
796
|
|
|
1194
|
-
|
|
797
|
+
*Nick Schwaderer*
|
|
1195
798
|
|
|
1196
|
-
|
|
799
|
+
* Make column name optional for `index_exists?`.
|
|
1197
800
|
|
|
1198
|
-
|
|
801
|
+
This aligns well with `remove_index` signature as well, where
|
|
802
|
+
index name doesn't need to be derived from the column names.
|
|
1199
803
|
|
|
1200
|
-
*
|
|
804
|
+
*Ali Ismayiliov*
|
|
1201
805
|
|
|
1202
|
-
*
|
|
1203
|
-
|
|
1204
|
-
new methods run `EXPLAIN` on the corresponding queries:
|
|
806
|
+
* Change the payload name of `sql.active_record` notification for eager
|
|
807
|
+
loading from "SQL" to "#{model.name} Eager Load".
|
|
1205
808
|
|
|
1206
|
-
|
|
1207
|
-
User.all.explain.count
|
|
1208
|
-
# EXPLAIN SELECT COUNT(*) FROM `users`
|
|
1209
|
-
# ...
|
|
809
|
+
*zzak*
|
|
1210
810
|
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
# ...
|
|
1214
|
-
```
|
|
811
|
+
* Enable automatically retrying idempotent `#exists?` queries on connection
|
|
812
|
+
errors.
|
|
1215
813
|
|
|
1216
|
-
*
|
|
814
|
+
*Hartley McGuire*, *classidied*
|
|
1217
815
|
|
|
1218
|
-
*
|
|
1219
|
-
when validating associated records.
|
|
816
|
+
* Deprecate usage of unsupported methods in conjunction with `update_all`:
|
|
1220
817
|
|
|
1221
|
-
|
|
818
|
+
`update_all` will now print a deprecation message if a query includes either `WITH`,
|
|
819
|
+
`WITH RECURSIVE` or `DISTINCT` statements. Those were never supported and were ignored
|
|
820
|
+
when generating the SQL query.
|
|
1222
821
|
|
|
1223
|
-
|
|
822
|
+
An error will be raised in a future Rails release. This behavior will be consistent
|
|
823
|
+
with `delete_all` which currently raises an error for unsupported statements.
|
|
1224
824
|
|
|
1225
|
-
|
|
1226
|
-
file takes precedence over Rails' defaults, and additional PRAGMAs can be
|
|
1227
|
-
set as well.
|
|
825
|
+
*Edouard Chin*
|
|
1228
826
|
|
|
1229
|
-
|
|
1230
|
-
database: storage/development.sqlite3
|
|
1231
|
-
timeout: 5000
|
|
1232
|
-
pragmas:
|
|
1233
|
-
journal_mode: off
|
|
1234
|
-
temp_store: memory
|
|
1235
|
-
```
|
|
827
|
+
* The table columns inside `schema.rb` are now sorted alphabetically.
|
|
1236
828
|
|
|
1237
|
-
|
|
829
|
+
Previously they'd be sorted by creation order, which can cause merge conflicts when two
|
|
830
|
+
branches modify the same table concurrently.
|
|
1238
831
|
|
|
1239
|
-
*
|
|
832
|
+
*John Duff*
|
|
1240
833
|
|
|
1241
|
-
|
|
1242
|
-
with care, so instead of a warning most users won't see anyway, it's preferable to
|
|
1243
|
-
leave the configuration commented out to force them to think about having the database
|
|
1244
|
-
on a persistent volume etc.
|
|
834
|
+
* Introduce versions formatter for the schema dumper.
|
|
1245
835
|
|
|
1246
|
-
|
|
836
|
+
It is now possible to override how schema dumper formats versions information inside the
|
|
837
|
+
`structure.sql` file. Currently, the versions are simply sorted in the decreasing order.
|
|
838
|
+
Within large teams, this can potentially cause many merge conflicts near the top of the list.
|
|
1247
839
|
|
|
1248
|
-
|
|
840
|
+
Now, the custom formatter can be provided with a custom sorting logic (e.g. by hash values
|
|
841
|
+
of the versions), which can greatly reduce the number of conflicts.
|
|
1249
842
|
|
|
1250
|
-
|
|
1251
|
-
This adds support for those to the SQLite3 adapter.
|
|
843
|
+
*fatkodima*
|
|
1252
844
|
|
|
1253
|
-
|
|
1254
|
-
create_table :users do |t|
|
|
1255
|
-
t.string :name
|
|
1256
|
-
t.virtual :name_upper, type: :string, as: 'UPPER(name)'
|
|
1257
|
-
t.virtual :name_lower, type: :string, as: 'LOWER(name)', stored: true
|
|
1258
|
-
end
|
|
1259
|
-
```
|
|
845
|
+
* Serialized attributes can now be marked as comparable.
|
|
1260
846
|
|
|
1261
|
-
|
|
847
|
+
A not rare issue when working with serialized attributes is that the serialized representation of an object
|
|
848
|
+
can change over time. Either because you are migrating from one serializer to the other (e.g. YAML to JSON or to msgpack),
|
|
849
|
+
or because the serializer used subtly changed its output.
|
|
1262
850
|
|
|
1263
|
-
|
|
851
|
+
One example is libyaml that used to have some extra trailing whitespaces, and recently fixed that.
|
|
852
|
+
When this sorts of thing happen, you end up with lots of records that report being changed even though
|
|
853
|
+
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.
|
|
1264
854
|
|
|
1265
|
-
|
|
855
|
+
The solution is to instead compare the deserialized representation of the object, however Active Record
|
|
856
|
+
can't assume the deserialized object has a working `==` method. Hence why this new functionality is opt-in.
|
|
1266
857
|
|
|
1267
|
-
```
|
|
1268
|
-
|
|
858
|
+
```ruby
|
|
859
|
+
serialize :config, type: Hash, coder: JSON, comparable: true
|
|
1269
860
|
```
|
|
1270
861
|
|
|
1271
862
|
*Jean Boussier*
|
|
1272
863
|
|
|
1273
|
-
*
|
|
1274
|
-
`assert_no_queries_match` assertions public.
|
|
864
|
+
* Fix MySQL default functions getting dropped when changing a column's nullability.
|
|
1275
865
|
|
|
1276
|
-
|
|
1277
|
-
`assert_no_queries`. To assert that specific SQL queries are made, `assert_queries_match` and
|
|
1278
|
-
`assert_no_queries_match` are used. These assertions can now be used in applications as well.
|
|
866
|
+
*Bastian Bartmann*
|
|
1279
867
|
|
|
1280
|
-
|
|
1281
|
-
class ArticleTest < ActiveSupport::TestCase
|
|
1282
|
-
test "queries are made" do
|
|
1283
|
-
assert_queries_count(1) { Article.first }
|
|
1284
|
-
end
|
|
868
|
+
* SQLite extensions can be configured in `config/database.yml`.
|
|
1285
869
|
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
870
|
+
The database configuration option `extensions:` allows an application to load SQLite extensions
|
|
871
|
+
when using `sqlite3` >= v2.4.0. The array members may be filesystem paths or the names of
|
|
872
|
+
modules that respond to `.to_path`:
|
|
873
|
+
|
|
874
|
+
``` yaml
|
|
875
|
+
development:
|
|
876
|
+
adapter: sqlite3
|
|
877
|
+
extensions:
|
|
878
|
+
- SQLean::UUID # module name responding to `.to_path`
|
|
879
|
+
- .sqlpkg/nalgeon/crypto/crypto.so # or a filesystem path
|
|
880
|
+
- <%= AppExtensions.location %> # or ruby code returning a path
|
|
1292
881
|
```
|
|
1293
882
|
|
|
1294
|
-
*
|
|
883
|
+
*Mike Dalessio*
|
|
1295
884
|
|
|
1296
|
-
*
|
|
885
|
+
* `ActiveRecord::Middleware::ShardSelector` supports granular database connection switching.
|
|
1297
886
|
|
|
1298
|
-
|
|
887
|
+
A new configuration option, `class_name:`, is introduced to
|
|
888
|
+
`config.active_record.shard_selector` to allow an application to specify the abstract connection
|
|
889
|
+
class to be switched by the shard selection middleware. The default class is
|
|
890
|
+
`ActiveRecord::Base`.
|
|
1299
891
|
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
set in the deployment environment.
|
|
892
|
+
For example, this configuration tells `ShardSelector` to switch shards using
|
|
893
|
+
`AnimalsRecord.connected_to`:
|
|
1303
894
|
|
|
1304
|
-
```
|
|
1305
|
-
|
|
1306
|
-
config.active_record.protocol_adapters.mysql = "trilogy"
|
|
1307
|
-
# will connect to MySQL using the trilogy adapter
|
|
895
|
+
```
|
|
896
|
+
config.active_record.shard_selector = { class_name: "AnimalsRecord" }
|
|
1308
897
|
```
|
|
1309
898
|
|
|
1310
|
-
*
|
|
899
|
+
*Mike Dalessio*
|
|
1311
900
|
|
|
1312
|
-
*
|
|
1313
|
-
the `SHOW WARNINGS` query is executed, `ActiveRecord.db_warnings_action` proc will still be
|
|
1314
|
-
called with a generic warning message rather than silently ignoring the warning(s).
|
|
901
|
+
* Reset relations after `insert_all`/`upsert_all`.
|
|
1315
902
|
|
|
1316
|
-
|
|
903
|
+
Bulk insert/upsert methods will now call `reset` if used on a relation, matching the behavior of `update_all`.
|
|
1317
904
|
|
|
1318
|
-
*
|
|
905
|
+
*Milo Winningham*
|
|
1319
906
|
|
|
1320
|
-
|
|
907
|
+
* Use `_N` as a parallel tests databases suffixes
|
|
1321
908
|
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
column).
|
|
909
|
+
Peviously, `-N` was used as a suffix. This can cause problems for RDBMSes
|
|
910
|
+
which do not support dashes in database names.
|
|
1325
911
|
|
|
1326
|
-
*
|
|
912
|
+
*fatkodima*
|
|
1327
913
|
|
|
1328
|
-
*
|
|
914
|
+
* Remember when a database connection has recently been verified (for
|
|
915
|
+
two seconds, by default), to avoid repeated reverifications during a
|
|
916
|
+
single request.
|
|
1329
917
|
|
|
1330
|
-
|
|
918
|
+
This should recreate a similar rate of verification as in Rails 7.1,
|
|
919
|
+
where connections are leased for the duration of a request, and thus
|
|
920
|
+
only verified once.
|
|
1331
921
|
|
|
1332
|
-
|
|
1333
|
-
Post.first.inspect #=> "#<Post id: 1>"
|
|
1334
|
-
```
|
|
922
|
+
*Matthew Draper*
|
|
1335
923
|
|
|
1336
|
-
|
|
1337
|
-
`ActiveRecord::Core#attributes_for_inspect`.
|
|
924
|
+
* Allow to reset cache counters for multiple records.
|
|
1338
925
|
|
|
1339
|
-
```ruby
|
|
1340
|
-
Post.attributes_for_inspect = [:id, :title]
|
|
1341
|
-
Post.first.inspect #=> "#<Post id: 1, title: "Hello, World!">"
|
|
1342
926
|
```
|
|
1343
|
-
|
|
1344
|
-
With `attributes_for_inspect` set to `:all`, `inspect` will list all the record's attributes.
|
|
1345
|
-
|
|
1346
|
-
```ruby
|
|
1347
|
-
Post.attributes_for_inspect = :all
|
|
1348
|
-
Post.first.inspect #=> "#<Post id: 1, title: "Hello, World!", published_at: "2023-10-23 14:28:11 +0000">"
|
|
927
|
+
Aircraft.reset_counters([1, 2, 3], :wheels_count)
|
|
1349
928
|
```
|
|
1350
929
|
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
You can also call `full_inspect` to get an inspection with all the attributes.
|
|
1354
|
-
|
|
1355
|
-
The attributes in `attribute_for_inspect` will also be used for `pretty_print`.
|
|
930
|
+
It produces much fewer queries compared to the custom implementation using looping over ids.
|
|
931
|
+
Previously: `O(ids.size * counters.size)` queries, now: `O(ids.size + counters.size)` queries.
|
|
1356
932
|
|
|
1357
|
-
*
|
|
1358
|
-
|
|
1359
|
-
* Don't mark attributes as changed when reassigned to `Float::INFINITY` or
|
|
1360
|
-
`-Float::INFINITY`.
|
|
1361
|
-
|
|
1362
|
-
*Maicol Bentancor*
|
|
933
|
+
*fatkodima*
|
|
1363
934
|
|
|
1364
|
-
*
|
|
935
|
+
* Add `affected_rows` to `sql.active_record` Notification.
|
|
1365
936
|
|
|
1366
|
-
*
|
|
937
|
+
*Hartley McGuire*
|
|
1367
938
|
|
|
1368
|
-
*
|
|
939
|
+
* Fix `sum` when performing a grouped calculation.
|
|
1369
940
|
|
|
1370
|
-
|
|
941
|
+
`User.group(:friendly).sum` no longer worked. This is fixed.
|
|
1371
942
|
|
|
1372
|
-
|
|
1373
|
-
add_reference :person, :alias, foreign_key: { deferrable: :deferred }
|
|
1374
|
-
add_reference :alias, :person, foreign_key: { deferrable: :deferred }
|
|
1375
|
-
```
|
|
943
|
+
*Edouard Chin*
|
|
1376
944
|
|
|
1377
|
-
|
|
945
|
+
* Add support for enabling or disabling transactional tests per database.
|
|
1378
946
|
|
|
1379
|
-
|
|
947
|
+
A test class can now override the default `use_transactional_tests` setting
|
|
948
|
+
for individual databases, which can be useful if some databases need their
|
|
949
|
+
current state to be accessible to an external process while tests are running.
|
|
1380
950
|
|
|
1381
951
|
```ruby
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
Post.connection.set_constraints(:deferred)
|
|
1386
|
-
p = Post.create!(user_id: -1)
|
|
1387
|
-
u = User.create!
|
|
1388
|
-
p.user = u
|
|
1389
|
-
p.save!
|
|
952
|
+
class MostlyTransactionalTest < ActiveSupport::TestCase
|
|
953
|
+
self.use_transactional_tests = true
|
|
954
|
+
skip_transactional_tests_for_database :shared
|
|
1390
955
|
end
|
|
1391
956
|
```
|
|
1392
957
|
|
|
1393
|
-
*
|
|
1394
|
-
|
|
1395
|
-
* Include `ActiveModel::API` in `ActiveRecord::Base`.
|
|
958
|
+
*Matthew Cheetham*, *Morgan Mareve*
|
|
1396
959
|
|
|
1397
|
-
|
|
960
|
+
* Cast `query_cache` value when using URL configuration.
|
|
1398
961
|
|
|
1399
|
-
*
|
|
1400
|
-
|
|
1401
|
-
*Jason Meller*
|
|
1402
|
-
|
|
1403
|
-
* Add `nulls_last` and working `desc.nulls_first` for MySQL.
|
|
962
|
+
*zzak*
|
|
1404
963
|
|
|
1405
|
-
|
|
964
|
+
* NULLS NOT DISTINCT works with UNIQUE CONSTRAINT as well as UNIQUE INDEX.
|
|
1406
965
|
|
|
1407
|
-
*
|
|
966
|
+
*Ryuta Kamizono*
|
|
1408
967
|
|
|
1409
|
-
|
|
1410
|
-
Topic.includes(:posts).order(posts: { created_at: :desc })
|
|
1411
|
-
```
|
|
968
|
+
* `PG::UnableToSend: no connection to the server` is now retryable as a connection-related exception
|
|
1412
969
|
|
|
1413
|
-
*
|
|
970
|
+
*Kazuma Watanabe*
|
|
1414
971
|
|
|
1415
|
-
Please check [
|
|
972
|
+
Please check [8-0-stable](https://github.com/rails/rails/blob/8-0-stable/activerecord/CHANGELOG.md) for previous changes.
|