activerecord 7.2.4 → 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.
Files changed (210) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1013 -878
  3. data/README.rdoc +1 -1
  4. data/lib/active_record/association_relation.rb +2 -1
  5. data/lib/active_record/associations/association.rb +69 -27
  6. data/lib/active_record/associations/association_scope.rb +1 -1
  7. data/lib/active_record/associations/belongs_to_association.rb +2 -2
  8. data/lib/active_record/associations/builder/association.rb +23 -11
  9. data/lib/active_record/associations/builder/belongs_to.rb +36 -8
  10. data/lib/active_record/associations/builder/collection_association.rb +7 -3
  11. data/lib/active_record/associations/builder/has_one.rb +1 -1
  12. data/lib/active_record/associations/builder/singular_association.rb +33 -5
  13. data/lib/active_record/associations/collection_association.rb +7 -3
  14. data/lib/active_record/associations/collection_proxy.rb +26 -4
  15. data/lib/active_record/associations/deprecation.rb +88 -0
  16. data/lib/active_record/associations/disable_joins_association_scope.rb +1 -1
  17. data/lib/active_record/associations/errors.rb +3 -0
  18. data/lib/active_record/associations/foreign_association.rb +3 -1
  19. data/lib/active_record/associations/has_many_through_association.rb +3 -2
  20. data/lib/active_record/associations/has_one_association.rb +1 -0
  21. data/lib/active_record/associations/join_dependency.rb +3 -2
  22. data/lib/active_record/associations/preloader/association.rb +3 -3
  23. data/lib/active_record/associations/preloader/batch.rb +7 -1
  24. data/lib/active_record/associations/preloader/branch.rb +1 -0
  25. data/lib/active_record/associations/singular_association.rb +8 -3
  26. data/lib/active_record/associations.rb +192 -24
  27. data/lib/active_record/asynchronous_queries_tracker.rb +28 -24
  28. data/lib/active_record/attribute_methods/primary_key.rb +4 -8
  29. data/lib/active_record/attribute_methods/query.rb +34 -0
  30. data/lib/active_record/attribute_methods/serialization.rb +18 -5
  31. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -14
  32. data/lib/active_record/attributes.rb +3 -0
  33. data/lib/active_record/autosave_association.rb +69 -27
  34. data/lib/active_record/base.rb +1 -2
  35. data/lib/active_record/callbacks.rb +1 -2
  36. data/lib/active_record/coders/column_serializer.rb +1 -1
  37. data/lib/active_record/coders/json.rb +16 -6
  38. data/lib/active_record/coders/yaml_column.rb +2 -2
  39. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +35 -28
  40. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +16 -4
  41. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +68 -13
  42. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +429 -93
  43. data/lib/active_record/connection_adapters/abstract/database_statements.rb +148 -74
  44. data/lib/active_record/connection_adapters/abstract/query_cache.rb +27 -5
  45. data/lib/active_record/connection_adapters/abstract/quoting.rb +16 -25
  46. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +11 -7
  47. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +32 -35
  48. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
  49. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +124 -34
  50. data/lib/active_record/connection_adapters/abstract/transaction.rb +40 -8
  51. data/lib/active_record/connection_adapters/abstract_adapter.rb +129 -63
  52. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +132 -65
  53. data/lib/active_record/connection_adapters/column.rb +14 -4
  54. data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -4
  55. data/lib/active_record/connection_adapters/mysql/quoting.rb +0 -8
  56. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
  57. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +41 -10
  58. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +79 -66
  59. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +89 -94
  60. data/lib/active_record/connection_adapters/mysql2_adapter.rb +2 -10
  61. data/lib/active_record/connection_adapters/pool_config.rb +7 -7
  62. data/lib/active_record/connection_adapters/postgresql/column.rb +8 -2
  63. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +79 -61
  64. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +3 -3
  65. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +10 -0
  66. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +46 -3
  67. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
  68. data/lib/active_record/connection_adapters/postgresql/quoting.rb +21 -10
  69. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -4
  70. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +9 -17
  71. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +14 -33
  72. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +71 -32
  73. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +156 -68
  74. data/lib/active_record/connection_adapters/postgresql_adapter.rb +78 -105
  75. data/lib/active_record/connection_adapters/schema_cache.rb +1 -3
  76. data/lib/active_record/connection_adapters/sqlite3/column.rb +8 -2
  77. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +90 -98
  78. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +0 -8
  79. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +0 -6
  80. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +27 -2
  81. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +15 -16
  82. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +104 -37
  83. data/lib/active_record/connection_adapters/statement_pool.rb +4 -2
  84. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +41 -66
  85. data/lib/active_record/connection_adapters/trilogy_adapter.rb +15 -18
  86. data/lib/active_record/connection_adapters.rb +1 -56
  87. data/lib/active_record/connection_handling.rb +25 -2
  88. data/lib/active_record/core.rb +33 -17
  89. data/lib/active_record/counter_cache.rb +35 -8
  90. data/lib/active_record/database_configurations/database_config.rb +9 -1
  91. data/lib/active_record/database_configurations/hash_config.rb +74 -9
  92. data/lib/active_record/database_configurations/url_config.rb +15 -3
  93. data/lib/active_record/database_configurations.rb +7 -3
  94. data/lib/active_record/delegated_type.rb +1 -1
  95. data/lib/active_record/disable_joins_association_relation.rb +5 -1
  96. data/lib/active_record/dynamic_matchers.rb +54 -69
  97. data/lib/active_record/encryption/config.rb +3 -1
  98. data/lib/active_record/encryption/encryptable_record.rb +8 -8
  99. data/lib/active_record/encryption/encrypted_attribute_type.rb +11 -2
  100. data/lib/active_record/encryption/encrypted_fixtures.rb +12 -7
  101. data/lib/active_record/encryption/encryptor.rb +28 -8
  102. data/lib/active_record/encryption/extended_deterministic_queries.rb +4 -2
  103. data/lib/active_record/encryption/scheme.rb +9 -2
  104. data/lib/active_record/enum.rb +33 -30
  105. data/lib/active_record/errors.rb +33 -9
  106. data/lib/active_record/explain.rb +1 -1
  107. data/lib/active_record/explain_registry.rb +51 -2
  108. data/lib/active_record/filter_attribute_handler.rb +76 -0
  109. data/lib/active_record/fixtures.rb +2 -4
  110. data/lib/active_record/future_result.rb +15 -9
  111. data/lib/active_record/gem_version.rb +2 -2
  112. data/lib/active_record/inheritance.rb +9 -4
  113. data/lib/active_record/insert_all.rb +14 -9
  114. data/lib/active_record/locking/optimistic.rb +8 -1
  115. data/lib/active_record/locking/pessimistic.rb +5 -0
  116. data/lib/active_record/log_subscriber.rb +31 -29
  117. data/lib/active_record/message_pack.rb +13 -0
  118. data/lib/active_record/middleware/shard_selector.rb +34 -17
  119. data/lib/active_record/migration/command_recorder.rb +56 -13
  120. data/lib/active_record/migration/compatibility.rb +37 -24
  121. data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
  122. data/lib/active_record/migration.rb +48 -42
  123. data/lib/active_record/model_schema.rb +40 -15
  124. data/lib/active_record/nested_attributes.rb +14 -12
  125. data/lib/active_record/persistence.rb +163 -133
  126. data/lib/active_record/query_cache.rb +22 -15
  127. data/lib/active_record/query_logs.rb +100 -52
  128. data/lib/active_record/query_logs_formatter.rb +17 -28
  129. data/lib/active_record/querying.rb +21 -9
  130. data/lib/active_record/railtie.rb +35 -30
  131. data/lib/active_record/railties/controller_runtime.rb +11 -6
  132. data/lib/active_record/railties/databases.rake +26 -38
  133. data/lib/active_record/railties/job_checkpoints.rb +15 -0
  134. data/lib/active_record/railties/job_runtime.rb +10 -11
  135. data/lib/active_record/reflection.rb +54 -22
  136. data/lib/active_record/relation/batches/batch_enumerator.rb +4 -3
  137. data/lib/active_record/relation/batches.rb +147 -73
  138. data/lib/active_record/relation/calculations.rb +60 -43
  139. data/lib/active_record/relation/delegation.rb +25 -15
  140. data/lib/active_record/relation/finder_methods.rb +73 -43
  141. data/lib/active_record/relation/merger.rb +12 -10
  142. data/lib/active_record/relation/predicate_builder/array_handler.rb +3 -1
  143. data/lib/active_record/relation/predicate_builder/association_query_value.rb +9 -9
  144. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +8 -8
  145. data/lib/active_record/relation/predicate_builder/relation_handler.rb +4 -3
  146. data/lib/active_record/relation/predicate_builder.rb +23 -8
  147. data/lib/active_record/relation/query_attribute.rb +3 -1
  148. data/lib/active_record/relation/query_methods.rb +200 -96
  149. data/lib/active_record/relation/spawn_methods.rb +7 -7
  150. data/lib/active_record/relation/where_clause.rb +2 -9
  151. data/lib/active_record/relation.rb +127 -87
  152. data/lib/active_record/result.rb +109 -24
  153. data/lib/active_record/runtime_registry.rb +42 -58
  154. data/lib/active_record/sanitization.rb +9 -6
  155. data/lib/active_record/schema.rb +1 -1
  156. data/lib/active_record/schema_dumper.rb +17 -10
  157. data/lib/active_record/schema_migration.rb +2 -1
  158. data/lib/active_record/scoping/named.rb +5 -2
  159. data/lib/active_record/scoping.rb +0 -1
  160. data/lib/active_record/signed_id.rb +44 -16
  161. data/lib/active_record/statement_cache.rb +24 -20
  162. data/lib/active_record/store.rb +53 -22
  163. data/lib/active_record/structured_event_subscriber.rb +85 -0
  164. data/lib/active_record/table_metadata.rb +6 -23
  165. data/lib/active_record/tasks/abstract_tasks.rb +83 -0
  166. data/lib/active_record/tasks/database_tasks.rb +85 -85
  167. data/lib/active_record/tasks/mysql_database_tasks.rb +4 -58
  168. data/lib/active_record/tasks/postgresql_database_tasks.rb +7 -40
  169. data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -28
  170. data/lib/active_record/test_databases.rb +18 -4
  171. data/lib/active_record/test_fixtures.rb +52 -6
  172. data/lib/active_record/testing/query_assertions.rb +8 -2
  173. data/lib/active_record/timestamp.rb +4 -2
  174. data/lib/active_record/token_for.rb +1 -1
  175. data/lib/active_record/transaction.rb +2 -5
  176. data/lib/active_record/transactions.rb +56 -32
  177. data/lib/active_record/type/hash_lookup_type_map.rb +2 -1
  178. data/lib/active_record/type/internal/timezone.rb +7 -0
  179. data/lib/active_record/type/json.rb +13 -2
  180. data/lib/active_record/type/serialized.rb +16 -4
  181. data/lib/active_record/type/type_map.rb +1 -1
  182. data/lib/active_record/type_caster/connection.rb +2 -1
  183. data/lib/active_record/validations/associated.rb +1 -1
  184. data/lib/active_record/validations/uniqueness.rb +8 -8
  185. data/lib/active_record.rb +85 -50
  186. data/lib/arel/alias_predication.rb +2 -0
  187. data/lib/arel/collectors/bind.rb +2 -2
  188. data/lib/arel/collectors/sql_string.rb +1 -1
  189. data/lib/arel/collectors/substitute_binds.rb +2 -2
  190. data/lib/arel/crud.rb +6 -11
  191. data/lib/arel/nodes/binary.rb +1 -1
  192. data/lib/arel/nodes/count.rb +2 -2
  193. data/lib/arel/nodes/function.rb +4 -10
  194. data/lib/arel/nodes/named_function.rb +2 -2
  195. data/lib/arel/nodes/node.rb +2 -2
  196. data/lib/arel/nodes/sql_literal.rb +1 -1
  197. data/lib/arel/nodes.rb +0 -2
  198. data/lib/arel/predications.rb +1 -3
  199. data/lib/arel/select_manager.rb +7 -2
  200. data/lib/arel/table.rb +3 -7
  201. data/lib/arel/visitors/dot.rb +0 -3
  202. data/lib/arel/visitors/postgresql.rb +55 -0
  203. data/lib/arel/visitors/sqlite.rb +55 -8
  204. data/lib/arel/visitors/to_sql.rb +4 -22
  205. data/lib/arel.rb +3 -1
  206. data/lib/rails/generators/active_record/application_record/USAGE +1 -1
  207. metadata +15 -12
  208. data/lib/active_record/explain_subscriber.rb +0 -34
  209. data/lib/active_record/normalization.rb +0 -163
  210. data/lib/active_record/relation/record_fetch_warning.rb +0 -52
data/CHANGELOG.md CHANGED
@@ -1,1459 +1,1594 @@
1
- ## Rails 7.2.4 (September 24, 2026) ##
1
+ ## Rails 8.1.4 (September 24, 2026) ##
2
2
 
3
- * Fix performance regression in `method_missing` for virtual SELECT alias
4
- attributes.
5
-
6
- Fixes #57183.
3
+ * Avoid deadlocks when concurrent `find_or_create_by` calls read back the same
4
+ record within MySQL transactions.
7
5
 
8
- *Hammad Khan*
6
+ Use a shared lock for the read after a duplicate insert, preserving visibility
7
+ under REPEATABLE READ without upgrading competing shared locks to exclusive locks.
8
+ This also applies to `create_or_find_by` and the bang variants of both methods.
9
9
 
10
- * Fix support for table names containing hyphens.
10
+ Fixes #54281.
11
11
 
12
- *Evgeniy Demin*
12
+ *Kirsten Westeinde*
13
13
 
14
- * Improve PostgreSQLAdapter resilience to Timeout.timeout.
15
-
16
- Better handle asynchronous exceptions being thrown inside
17
- the `reconnect!` method.
18
-
19
- This may fixes some deep errors such as:
20
-
21
- ```
22
- undefined method `key?' for nil:NilClass (NoMethodError)
23
- if !type_map.key?(oid)
24
- ```
14
+ * Filter the database password out of failed `db:` task command error messages.
25
15
 
26
- *Jean Boussier*
16
+ *Ngan Pham*
27
17
 
28
- * Fix `eager_load` when loading `has_many` assocations with composite primary keys.
18
+ * Fix `ActiveRecord::TypeCaster::Connection` sometimes leaking a checked-out
19
+ connection.
29
20
 
30
- This would result in some records being loaded multiple times.
21
+ *Hartley McGuire*
31
22
 
32
- *Martin-Alexander*
23
+ * Fix PostgreSQL exclusion constraints with multiline expressions being parsed
24
+ incorrectly during schema introspection.
33
25
 
26
+ *Jake McAllister*
34
27
 
35
- ## Rails 7.2.3.2 (July 29, 2026) ##
28
+ * Fix async `ActiveRecord::StatementCache#execute` raising an error for
29
+ out-of-range bind values instead of returning an empty result.
36
30
 
37
- * No changes.
31
+ *viralpraxis*
38
32
 
33
+ * Fix `where` clauses with column-tuple syntax not resolving references to
34
+ other tables.
39
35
 
40
- ## Rails 7.2.3.1 (March 23, 2026) ##
36
+ *Chris Gunther*
41
37
 
42
- * No changes.
38
+ * Fix `distinct: true` being ignored by `average`.
43
39
 
40
+ *Kenta Ishizaki*
44
41
 
45
- ## Rails 7.2.3 (October 28, 2025) ##
42
+ * Fix `belongs_to` change tracking for composite foreign keys.
46
43
 
47
- * Fix SQLite3 data loss during table alterations with CASCADE foreign keys.
44
+ Only the first foreign key column was checked for changes; now all foreign
45
+ key columns are checked.
48
46
 
49
- When altering a table in SQLite3 that is referenced by child tables with
50
- `ON DELETE CASCADE` foreign keys, ActiveRecord would silently delete all
51
- data from the child tables. This occurred because SQLite requires table
52
- recreation for schema changes, and during this process the original table
53
- is temporarily dropped, triggering CASCADE deletes on child tables.
47
+ *Anas Khan*
54
48
 
55
- The root cause was incorrect ordering of operations. The original code
56
- wrapped `disable_referential_integrity` inside a transaction, but
57
- `PRAGMA foreign_keys` cannot be modified inside a transaction in SQLite -
58
- attempting to do so simply has no effect. This meant foreign keys remained
59
- enabled during table recreation, causing CASCADE deletes to fire.
49
+ * Make `add_column(if_not_exists: true)` reversible.
60
50
 
61
- The fix reverses the order to follow the official SQLite 12-step ALTER TABLE
62
- procedure: `disable_referential_integrity` now wraps the transaction instead
63
- of being wrapped by it. This ensures foreign keys are properly disabled
64
- before the transaction starts and re-enabled after it commits, preventing
65
- CASCADE deletes while maintaining data integrity through atomic transactions.
51
+ *Kenta Ishizaki*
66
52
 
67
- *Ruy Rocha*
53
+ * Quote the index name in MySQL `enable_index` and `disable_index`.
68
54
 
69
- * Fix `belongs_to` associations not to clear the entire composite primary key.
55
+ Unquoted index names containing special characters could cause SQL syntax
56
+ errors.
70
57
 
71
- When clearing a `belongs_to` association that references a model with composite primary key,
72
- only the optional part of the key should be cleared.
58
+ *Kenta Ishizaki*
73
59
 
74
- *zzak*
60
+ * Make `remove_foreign_key(if_exists: true)` reversible.
75
61
 
76
- * Fix invalid records being autosaved when distantly associated records are marked for deletion.
62
+ *Kenta Ishizaki*
77
63
 
78
- *Ian Terrell*, *axlekb AB*
64
+ * Fix `distinct: true` being ignored by grouped `sum`.
79
65
 
80
- * Prevent persisting invalid record.
66
+ *Kenta Ishizaki*
81
67
 
82
- *Edouard Chin*
68
+ * Return an `ActiveRecord::Promise` from `async_ids` on a contradictory
69
+ relation, instead of a plain `ActiveRecord::Result`.
83
70
 
84
- * Fix count with group by qualified name on loaded relation.
71
+ *Kenta Ishizaki*
85
72
 
86
- *Ryuta Kamizono*
73
+ * Fix reversibility check for `drop_virtual_table`.
87
74
 
88
- * Fix `sum` with qualified name on loaded relation.
75
+ The wrong argument was extracted, so the check for whether options were
76
+ given could pass or fail incorrectly.
89
77
 
90
- *Chris Gunther*
78
+ *Kenta Ishizaki*
91
79
 
92
- * Fix prepared statements on mysql2 adapter.
80
+ * Fix `remove_check_constraint(if_exists: true)` incorrectly raising when
81
+ removing by expression.
93
82
 
94
- *Jean Boussier*
83
+ The `if_exists` check did not pass the expression to
84
+ `check_constraint_exists?`, so it could not find the constraint.
95
85
 
96
- * Fix query cache for pinned connections in multi threaded transactional tests.
86
+ *Kenta Ishizaki*
97
87
 
98
- When a pinned connection is used across separate threads, they now use a separate cache store
99
- for each thread.
88
+ * Clear PostgreSQL notices as they are handled, preventing warnings from
89
+ leaking to subsequent queries.
100
90
 
101
- This improve accuracy of system tests, and any test using multiple threads.
91
+ *Matthew Draper*
102
92
 
103
- *Heinrich Lee Yu*, *Jean Boussier*
93
+ * Fix `WeakThreadKeyMap` raising "can't add a new key into hash during
94
+ iteration" when connections are checked in from multiple threads.
104
95
 
105
- * Don't add `id_value` attribute alias when attribute/column with that name already exists.
96
+ *Matthew Draper*
106
97
 
107
- *Rob Lewis*
98
+ * Continue pool disconnect after a connection's cleanup or disconnect raises.
108
99
 
109
- * Fix false positive change detection involving STI and polymorhic has one relationships.
100
+ Previously, a failure on one connection aborted the teardown, stranding
101
+ remaining connections and their resources.
110
102
 
111
- Polymorphic `has_one` relationships would always be considered changed when defined in a STI child
112
- class, causing nedless extra autosaves.
103
+ *Matthew Draper*
113
104
 
114
- *David Fritsch*
105
+ * Fix race condition between `preconnect` and the connection pool reaper.
115
106
 
116
- * Fix stale associaton detection for polymophic `belong_to`.
107
+ *Yasuo Honda*
117
108
 
118
- *Florent Beaurain*, *Thomas Crambert*
109
+ * Fix `in_order_of` raising when the column is a CTE reference.
119
110
 
120
- * Fix removal of PostgreSQL version comments in `structure.sql` for latest PostgreSQL versions which include `\restrict`.
111
+ *viralpraxis*
121
112
 
122
- *Brendan Weibrecht*
113
+ * Fix `content_columns` including composite primary key components.
123
114
 
124
- * Fix `#merge` with `#or` or `#and` and a mixture of attributes and SQL strings resulting in an incorrect query.
115
+ Only the first primary key column was excluded; now all primary key columns
116
+ are excluded.
125
117
 
126
- ```ruby
127
- base = Comment.joins(:post).where(user_id: 1).where("recent = 1")
128
- puts base.merge(base.where(draft: true).or(Post.where(archived: true))).to_sql
129
- ```
118
+ *Kenta Ishizaki*
130
119
 
131
- Before:
120
+ * Treat `remove_column` with options but no type as irreversible.
132
121
 
133
- ```SQL
134
- SELECT "comments".* FROM "comments"
135
- INNER JOIN "posts" ON "posts"."id" = "comments"."post_id"
136
- WHERE (recent = 1)
137
- AND (
138
- "comments"."user_id" = 1
139
- AND (recent = 1)
140
- AND "comments"."draft" = 1
141
- OR "posts"."archived" = 1
142
- )
143
- ```
122
+ Previously, `remove_column(:table, :column, default: nil)` would not raise
123
+ `IrreversibleMigration` because the options hash was mistaken for a column
124
+ type.
144
125
 
145
- After:
126
+ *Kenta Ishizaki*
146
127
 
147
- ```SQL
148
- SELECT "comments".* FROM "comments"
149
- INNER JOIN "posts" ON "posts"."id" = "comments"."post_id"
150
- WHERE "comments"."user_id" = 1
151
- AND (recent = 1)
152
- AND (
153
- "comments"."user_id" = 1
154
- AND (recent = 1)
155
- AND "comments"."draft" = 1
156
- OR "posts"."archived" = 1
157
- )
158
- ```
128
+ * Fix `counter_cache_column` crashing when `:counter_cache` is given as a
129
+ Hash without a `:column` key.
159
130
 
160
- *Joshua Young*
131
+ *Kenta Ishizaki*
161
132
 
162
- * Fix inline `has_and_belongs_to_many` fixtures for tables with composite primary keys.
133
+ * Coerce `seeds` and `use_metadata_table` to booleans in `UrlConfig`.
163
134
 
164
- *fatkodima*
135
+ When configured via `DATABASE_URL`, these options were left as strings
136
+ instead of being coerced to booleans like `replica` and `database_tasks`.
165
137
 
166
- * Fix `annotate` comments to propagate to `update_all`/`delete_all`.
138
+ *Kenta Ishizaki*
167
139
 
168
- *fatkodima*
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.
169
143
 
170
- * Fix checking whether an unpersisted record is `include?`d in a strictly
171
- loaded `has_and_belongs_to_many` association.
144
+ *Kenta Ishizaki*
172
145
 
173
- *Hartley McGuire*
146
+ * Fix `Relation#delete` raising on a single composite primary key id.
174
147
 
175
- * Fix inline has_and_belongs_to_many fixtures for tables with composite primary keys.
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.
176
150
 
177
- *fatkodima*
151
+ *Kenta Ishizaki*
178
152
 
179
- * `create_or_find_by` will now correctly rollback a transaction.
153
+ * Fix reading a composite primary key after a partial `select` returning the
154
+ raw value instead of `nil` for unselected key columns.
180
155
 
181
- When using `create_or_find_by`, raising a ActiveRecord::Rollback error
182
- in a `after_save` callback had no effect, the transaction was committed
183
- and a record created.
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.
184
160
 
185
- *Edouard Chin*
161
+ *Kenta Ishizaki*
186
162
 
187
- * Gracefully handle `Timeout.timeout` firing during connection configuration.
163
+ * Fix `find` with an empty array on a composite primary key model returning the
164
+ argument array instead of `[]`.
188
165
 
189
- Use of `Timeout.timeout` could result in improperly initialized database connection.
166
+ `Model.find([])` now returns a fresh empty array for composite primary key
167
+ models, matching single-key models.
190
168
 
191
- This could lead to a partially configured connection being used, resulting in various exceptions,
192
- the most common being with the PostgreSQLAdapter raising `undefined method 'key?' for nil`
193
- or `TypeError: wrong argument type nil (expected PG::TypeMap)`.
169
+ *Kenta Ishizaki*
194
170
 
195
- *Jean Boussier*
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.
196
173
 
197
- * The SQLite3 adapter quotes non-finite Numeric values like "Infinity" and "NaN".
174
+ *Kenta Ishizaki*
198
175
 
199
- *Mike Dalessio*
176
+ * Fix `in_order_of` dropping values that cannot be serialized for the column
177
+ instead of turning them into an `IS NULL` match.
200
178
 
201
- * Handle libpq returning a database version of 0 on no/bad connection in `PostgreSQLAdapter`.
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.
202
183
 
203
- Before, this version would be cached and an error would be raised during connection configuration when
204
- comparing it with the minimum required version for the adapter. This meant that the connection could
205
- never be successfully configured on subsequent reconnection attempts.
184
+ *Kenta Ishizaki*
206
185
 
207
- Now, this is treated as a connection failure consistent with libpq, raising a `ActiveRecord::ConnectionFailed`
208
- and ensuring the version isn't cached, which allows the version to be retrieved on the next connection attempt.
186
+ * Fix stale `finder_needs_type_condition?` memo after the schema cache is reloaded.
209
187
 
210
- *Joshua Young*, *Rian McGuire*
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`.
211
192
 
212
- * Fix error handling during connection configuration.
193
+ *Kenta Ishizaki*
213
194
 
214
- Active Record wasn't properly handling errors during the connection configuration phase.
215
- This could lead to a partially configured connection being used, resulting in various exceptions,
216
- the most common being with the PostgreSQLAdapter raising `undefined method `key?' for nil`
217
- or `TypeError: wrong argument type nil (expected PG::TypeMap)`.
195
+ * Fix PostgreSQL schema dump to qualify `enum_type` when the same enum name exists
196
+ in different schemas.
218
197
 
219
- *Jean Boussier*
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.
220
200
 
221
- * Fix a case where a non-retryable query could be marked retryable.
201
+ *fatkodima*
222
202
 
223
- *Hartley McGuire*
203
+ * Fix PostgreSQL index introspection to parse opclasses from another schema.
224
204
 
225
- * Handle circular references when autosaving associations.
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.
226
208
 
227
- *zzak*
209
+ *Nicolas Vandenboegaerde*
228
210
 
229
- * Prevent persisting invalid record.
211
+ * Fix `belongs_to` `:touch` with composite foreign keys.
230
212
 
231
- *Edouard Chin*
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.
232
216
 
233
- * Fix support for PostgreSQL enum types with commas in their name.
217
+ *Romulo Storel*
234
218
 
235
- *Arthur Hess*
219
+ * Fix `add_index` `comment:` option on a schema-qualified PostgreSQL table.
236
220
 
237
- * Fix inserts on MySQL with no RETURNING support for a table with multiple auto populated columns.
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.
238
223
 
239
- *Nikita Vasilevsky*
224
+ *Tobias Egli*
240
225
 
241
- * Fix joining on a scoped association with string joins and bind parameters.
226
+ * Fix `check_all_foreign_keys_valid!` on PostgreSQL partitioned tables.
242
227
 
243
- ```ruby
244
- class Instructor < ActiveRecord::Base
245
- has_many :instructor_roles, -> { active }
246
- end
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.
247
231
 
248
- class InstructorRole < ActiveRecord::Base
249
- scope :active, -> {
250
- joins("JOIN students ON instructor_roles.student_id = students.id")
251
- .where(students { status: 1 })
252
- }
253
- end
232
+ *Alexis Andrieu*
254
233
 
255
- Instructor.joins(:instructor_roles).first
256
- ```
234
+ * Revert stable sorting of columns and indexes in serialized schema caches.
257
235
 
258
- The above example would result in `ActiveRecord::StatementInvalid` because the
259
- `active` scope bind parameters would be lost.
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.
260
238
 
261
239
  *Jean Boussier*
262
240
 
263
- * Fix a potential race condition with system tests and transactional fixtures.
241
+ * Fix `only_columns` to enumerate columns in the `SELECT` clause.
264
242
 
265
- *Sjoerd Lagarde*
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.
266
245
 
267
- * Fix count with group by qualified name on loaded relation.
246
+ *sarub0b0*
268
247
 
269
- *Ryuta Kamizono*
248
+ * Fix `eager_load` with a composite primary key and an explicit `select`.
270
249
 
271
- * Fix sum with qualified name on loaded relation.
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.
272
253
 
273
- *Chris Gunther*
254
+ *fatkodima*
274
255
 
275
- * Fix autosave associations to no longer validated unmodified associated records.
256
+ * Fix `find_signed` with a composite primary key.
276
257
 
277
- Active Record was incorrectly performing validation on associated record that
278
- weren't created nor modified as part of the transaction:
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`.
279
260
 
280
- ```ruby
281
- Post.create!(author: User.find(1)) # Fail if user is invalid
282
- ```
261
+ *Kenta Ishizaki*
283
262
 
284
- *Jean Boussier*
263
+ * Fix `with_connection(prevent_permanent_checkout: true)` clearing a sticky lease
264
+ that was already set by `lease_connection`.
285
265
 
286
- * Remember when a database connection has recently been verified (for
287
- two seconds, by default), to avoid repeated reverifications during a
288
- single request.
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.
289
269
 
290
- This should recreate a similar rate of verification as in Rails 7.1,
291
- where connections are leased for the duration of a request, and thus
292
- only verified once.
270
+ *Ben Sheldon*
293
271
 
294
- *Matthew Draper*
272
+ * Fix `reset_counters` to cast string ids to the primary key type.
295
273
 
296
- * Fix prepared statements on mysql2 adapter.
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.
297
277
 
298
- *Jean Boussier*
299
-
300
- * Fix a race condition in `ActiveRecord::Base#method_missing` when lazily defining attributes.
278
+ *fatkodima*
301
279
 
302
- If multiple thread were concurrently triggering attribute definition on the same model,
303
- it could result in a `NoMethodError` being raised.
280
+ * Fix `belongs_to` presence validation for composite foreign keys.
304
281
 
305
- *Jean Boussier*
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.
306
285
 
307
- * Fix MySQL default functions getting dropped when changing a column's nullability.
286
+ *Felix Descoteaux*
308
287
 
309
- *Bastian Bartmann*
288
+ * Fix preloading a `belongs_to` with a composite foreign key when some key columns
289
+ are `nil`.
310
290
 
311
- * Fix `add_unique_constraint`/`add_check_constraint`/`/`add_foreign_key` to be revertible when
312
- given invalid options.
291
+ The preloader now skips owners whose composite key has any `nil` component
292
+ instead of issuing a query that matches unrelated rows.
313
293
 
314
- *fatkodima*
294
+ *Rose Wiegley*
315
295
 
316
- * Fix asynchronous destroying of polymorphic `belongs_to` associations.
296
+ * Fix `belongs_to` inverse matching with composite foreign keys.
317
297
 
318
- *fatkodima*
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.
319
302
 
320
- * NOT VALID constraints should not dump in `create_table`.
303
+ *Martin Samson*
321
304
 
322
- *Ryuta Kamizono*
305
+ * Fix `validate_table_length!` to ignore the schema prefix on PostgreSQL.
323
306
 
324
- * Fix finding by nil composite primary key association.
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.
325
310
 
326
311
  *fatkodima*
327
312
 
328
- * Fix parsing of SQLite foreign key names when they contain non-ASCII characters
313
+ * Fix passing Trilogy SSL options to `mysql` and `mysqldump` commands.
329
314
 
330
- *Zacharias Knudsen*
315
+ *Ngan Pham*
331
316
 
332
- * Fix parsing of MySQL 8.0.16+ CHECK constraints when they contain new lines.
317
+ * Fix `keepalive: false` in `database.yml` falling back to the
318
+ 600 second default.
333
319
 
334
- *Steve Hill*
320
+ *Joe Sak*
335
321
 
336
- * Ensure normalized attribute queries use `IS NULL` consistently for `nil` and normalized `nil` values.
322
+ * Fix connection checkout blocking past the configured `checkout_timeout` while
323
+ waiting behind background connection maintenance.
337
324
 
338
- *Joshua Young*
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.
339
330
 
340
- * Restore back the ability to pass only database name for `DATABASE_URL`.
331
+ *Joe Sak*
341
332
 
342
- *fatkodima*
333
+ * Fix encrypted fixtures for JSON columns.
343
334
 
344
- * Fix `order` with using association name as an alias.
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.
345
340
 
346
- *Ryuta Kamizono*
341
+ *Carlos Daniel Pohlod*
347
342
 
348
- * Improve invalid argument error for with.
343
+ * Fix performance regression in `method_missing` for virtual SELECT alias
344
+ attributes.
349
345
 
350
- *Ryuta Kamizono*
346
+ Fixes #57183.
351
347
 
352
- * Deduplicate `with` CTE expressions.
348
+ *Hammad Khan*
353
349
 
354
- *fatkodima*
350
+ * Column defaults are no longer eagerly deserialized.
355
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.
356
354
 
357
- ## Rails 7.2.2.2 (August 13, 2025) ##
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.
358
357
 
359
- * Call inspect on ids in RecordNotFound error
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.
360
361
 
361
- [CVE-2025-55193]
362
+ Before:
362
363
 
363
- *Gannon McGibbon*, *John Hawthorn*
364
+ ```ruby
365
+ Person.columns_hash["age"].default # => 0
366
+ ```
364
367
 
368
+ After:
365
369
 
366
- ## Rails 7.2.2.1 (December 10, 2024) ##
370
+ ```ruby
371
+ Person.columns_hash["age"].default # => "0"
372
+ ```
367
373
 
368
- * No changes.
374
+ See https://github.com/rails/rails/issues/58292.
369
375
 
376
+ *Jean Boussier*
370
377
 
371
- ## Rails 7.2.2 (October 30, 2024) ##
378
+ * Preserve the declared parent order when dumping PostgreSQL `INHERITS` table options.
372
379
 
373
- * Fix support for `query_cache: false` in `database.yml`.
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`.
374
383
 
375
- `query_cache: false` would no longer entirely disable the Active Record query cache.
384
+ *viralpraxis*
376
385
 
377
- *zzak*
386
+ * Preserve SQLite partial and expression indexes when their stored SQL contains newlines.
378
387
 
379
- * Set `.attributes_for_inspect` to `:all` by default.
388
+ *Javi Ramírez*
380
389
 
381
- For new applications it is set to `[:id]` in config/environment/production.rb.
390
+ * Only use multi statement for `SET TRANSACTION ISOLATION LEVEL; BEGIN` if
391
+ MySQL connection is configured to use multi statement.
382
392
 
383
- In the console all the attributes are always shown.
393
+ *Eliseu Daroit*, *Hartley McGuire*, *Matthew Draper*
384
394
 
385
- *Andrew Novoselac*
395
+ * Mark a connection unverified when a non-`StandardError` interrupts a query.
386
396
 
387
- * `PG::UnableToSend: no connection to the server` is now retryable as a connection-related exception
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.
388
402
 
389
- *Kazuma Watanabe*
403
+ *Eliseu Daroit*
390
404
 
391
- * Fix marshalling of unsaved associated records in 7.1 format.
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.
392
408
 
393
- The 7.1 format would only marshal associated records if the association was loaded.
394
- But associations that would only contain unsaved records would be skipped.
409
+ *Jean-Samuel Aubry-Guzzi*
395
410
 
396
- *Jean Boussier*
411
+ * Fix inverse association matching for `has_many` and `has_one` associations
412
+ with association-specific composite primary keys.
397
413
 
398
- * Fix incorrect SQL query when passing an empty hash to `ActiveRecord::Base.insert`.
414
+ *Hugo Vacher*
399
415
 
400
- *David Stosik*
416
+ * Fix `ActiveRecord::Base.with` to call `Object#with` when given a block.
401
417
 
402
- * Allow to save records with polymorphic join tables that have `inverse_of`
403
- specified.
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.
404
422
 
405
- *Markus Doits*
423
+ *Janko Marohnić*
406
424
 
407
- * Fix association scopes applying on the incorrect join when using a polymorphic `has_many through:`.
425
+ * Fix `serialize` with `coder: ActiveRecord::Coders::JSON` silently double-encoding
426
+ a native `json`/`jsonb` column.
408
427
 
409
- *Joshua Young*
428
+ *Kenta Ishizaki*
410
429
 
411
- * Fix `dependent: :destroy` for bi-directional has one through association.
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.
412
433
 
413
- Fixes #50948.
434
+ *Kenta Ishizaki*
414
435
 
415
- ```ruby
416
- class Left < ActiveRecord::Base
417
- has_one :middle, dependent: :destroy
418
- has_one :right, through: :middle
419
- end
436
+ * Fix `ActiveRecord::Relation#cache_key` / `cache_version` for a loaded collection
437
+ containing a record without a timestamp.
420
438
 
421
- class Middle < ActiveRecord::Base
422
- belongs_to :left, dependent: :destroy
423
- belongs_to :right, dependent: :destroy
424
- end
439
+ *Kenta Ishizaki*
425
440
 
426
- class Right < ActiveRecord::Base
427
- has_one :middle, dependent: :destroy
428
- has_one :left, through: :middle
429
- end
430
- ```
431
- In the above example `left.destroy` wouldn't destroy its associated `Right`
432
- record.
441
+ * Fix model `filter_attributes` to not add useless filters into `config.filter_parameters`.
433
442
 
434
- *Andy Stewart*
443
+ Proc and Regexp filters would be improperly turned into string matchers.
444
+ Now they are skipped.
435
445
 
436
- * Properly handle lazily pinned connection pools.
446
+ *Jonathan Calvert*
437
447
 
438
- Fixes #53147.
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.
439
451
 
440
- When using transactional fixtures with system tests to similar tools
441
- such as capybara, it could happen that a connection end up pinned by the
442
- server thread rather than the test thread, causing
443
- `"Cannot expire connection, it is owned by a different thread"` errors.
452
+ *Kenta Ishizaki*
444
453
 
445
- *Jean Boussier*
454
+ * Fix replacing or clearing a polymorphic `has_one` leaving a stale type column
455
+ on the removed record.
446
456
 
447
- * Fix `ActiveRecord::Base.with` to accept more than two sub queries.
457
+ *Kenta Ishizaki*
448
458
 
449
- Fixes #53110.
459
+ * Fix `accepts_nested_attributes_for` `:limit` miscounting a single-record hash.
450
460
 
451
- ```ruby
452
- User.with(foo: [User.select(:id), User.select(:id), User.select(:id)]).to_sql
453
- undefined method `union' for an instance of Arel::Nodes::UnionAll (NoMethodError)
454
- ```
461
+ *Kenta Ishizaki*
455
462
 
456
- The above now works as expected.
463
+ * Fix `rename_index` to preserve a partial index's `WHERE` for SQLite and older MySQL/MariaDB versions.
457
464
 
458
- *fatkodima*
465
+ *Kenta Ishizaki*
459
466
 
460
- * Properly release pinned connections with non joinable connections.
467
+ * Fix PostgreSQL `foreign_keys` returning a corrupted `to_table` for a foreign key
468
+ that references a table in a quoted schema.
461
469
 
462
- Fixes #52973
470
+ *Kenta Ishizaki*
463
471
 
464
- When running system tests with transactional fixtures on, it could happen that
465
- the connection leased by the Puma thread wouldn't be properly released back to the pool,
466
- causing "Cannot expire connection, it is owned by a different thread" errors in later tests.
472
+ * Fix grouped calculations (e.g. `count`) grouped by a `belongs_to` association
473
+ that points to a composite primary key model.
467
474
 
468
- *Jean Boussier*
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.
469
479
 
470
- * Make Float distinguish between `float4` and `float8` in PostgreSQL.
480
+ *Kenta Ishizaki*
471
481
 
472
- Fixes #52742
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.
473
485
 
474
- *Ryota Kitazawa*, *Takayuki Nagatomi*
486
+ *Kenta Ishizaki*
475
487
 
476
- * Fix an issue where `.left_outer_joins` used with multiple associations that have
477
- the same child association but different parents does not join all parents.
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).
478
491
 
479
- Previously, using `.left_outer_joins` with the same child association would only join one of the parents.
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).
480
496
 
481
- Now it will correctly join both parents.
497
+ *Kenta Ishizaki*
482
498
 
483
- Fixes #41498.
499
+ * Fix `find` with multiple composite primary key ids passed as strings
500
+ silently returning `[]`.
484
501
 
485
- *Garrett Blehm*
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.
486
509
 
487
- * Ensure `ActiveRecord::Encryption.config` is always ready before access.
510
+ *Kenta Ishizaki*
488
511
 
489
- Previously, `ActiveRecord::Encryption` configuration was deferred until `ActiveRecord::Base`
490
- was loaded. Therefore, accessing `ActiveRecord::Encryption.config` properties before
491
- `ActiveRecord::Base` was loaded would give incorrect results.
512
+ * Fix PostgreSQL `daterange` / `tsrange` / `tstzrange` schema dump producing
513
+ invalid Ruby.
492
514
 
493
- `ActiveRecord::Encryption` now has its own loading hook so that its configuration is set as
494
- soon as needed.
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.
495
521
 
496
- When `ActiveRecord::Base` is loaded, even lazily, it in turn triggers the loading of
497
- `ActiveRecord::Encryption`, thus preserving the original behavior of having its config ready
498
- before any use of `ActiveRecord::Base`.
522
+ *Kenta Ishizaki*
499
523
 
500
- *Maxime Réty*
524
+ * Fix deadlock when pool-less connection materializes while fetching database
525
+ server version.
501
526
 
502
- * Add `TimeZoneConverter#==` method, so objects will be properly compared by
503
- their type, scale, limit & precision.
527
+ *Hartley McGuire*
504
528
 
505
- Address #52699.
529
+ * Fix PostgreSQL range columns corrupting bounds that contain a comma.
506
530
 
507
- *Ruy Rocha*
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.
508
537
 
538
+ *Kenta Ishizaki*
509
539
 
510
- ## Rails 7.2.1.2 (October 23, 2024) ##
540
+ * Fix store accessor `*_change` and `saved_change_to_*` reporting a change
541
+ for unchanged keys.
511
542
 
512
- * No changes.
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.
513
550
 
551
+ *Kenta Ishizaki*
514
552
 
515
- ## Rails 7.2.1.1 (October 15, 2024) ##
553
+ * Reduce number of queries when introspecting MySQL/MariaDB tables.
516
554
 
517
- * No changes.
555
+ A fix to support MariaDB function defaults caused the MySQL adapters to
556
+ issue one query per column when introspecting tables.
518
557
 
558
+ Now it only issue a single extra query per table, and only when using MariaDB.
519
559
 
520
- ## Rails 7.2.1 (August 22, 2024) ##
560
+ *Iliana Hadzhiatanasova*
521
561
 
522
- * Fix detection for `enum` columns with parallelized tests and PostgreSQL.
562
+ * Fully qualify query criterias in `has_and_belongs_to_many` associations.
523
563
 
524
- *Rafael Mendonça França*
564
+ Ensure that scopes with the same column name but in different tables aren't lost
565
+ when following an HABTM association.
525
566
 
526
- * Allow to eager load nested nil associations.
567
+ *Philip Maina*
527
568
 
528
- *fatkodima*
569
+ * Fix Active Record Pool Reaper thread leak after `Parallelization#shutdown`.
529
570
 
530
- * Fix swallowing ignore order warning when batching using `BatchEnumerator`.
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).
531
574
 
532
- *fatkodima*
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.
533
579
 
534
- * Fix memory bloat on the connection pool when using the Fiber `IsolatedExecutionState`.
580
+ *Ruy Rocha*
535
581
 
536
- *Jean Boussier*
582
+ * Fix duplicate `WHERE` conditions in `create_or_find_by`.
537
583
 
538
- * Restore inferred association class with the same modularized name.
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.
539
585
 
540
- *Justin Ko*
586
+ *Yavor Dashev*
541
587
 
542
- * Fix `ActiveRecord::Base.inspect` to properly explain how to load schema information.
588
+ * Fix `ActiveRecord::QueryMethods#in_order_of` when passing an out-of-range Integer
543
589
 
544
- *Jean Boussier*
590
+ To match the behavior of the `Enumerable` version, `in_order_of` now ignores an out-of-range Integer.
545
591
 
546
- * Check invalid `enum` options for the new syntax.
592
+ *tejanium*
547
593
 
548
- The options using `_` prefix in the old syntax are invalid in the new syntax.
594
+ * Revert alphabetical sorting of table columns inside `schema.rb`.
549
595
 
550
- *Rafael Mendonça França*
596
+ Alphabetical sorting of table columns inside the schema creates improper production tables when using `db:prepare`.
551
597
 
552
- * Fix `ActiveRecord::Encryption::EncryptedAttributeType#type` to return
553
- actual cast type.
598
+ *Bert McCutchen*
554
599
 
555
- *Vasiliy Ermolovich*
600
+ * Fix `strict_loading` violations ignored when using `pluck`
556
601
 
557
- * Fix `create_table` with `:auto_increment` option for MySQL adapter.
602
+ *Johnson Chan*
558
603
 
559
- *fatkodima*
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`.
560
606
 
607
+ *Joshua Young*
561
608
 
562
- ## Rails 7.2.0 (August 09, 2024) ##
609
+ * Fix `becomes` to preserve `marked_for_destruction?`.
563
610
 
564
- * Handle commas in Sqlite3 default function definitions.
611
+ *Vincent Robert*
565
612
 
566
- *Stephen Margheim*
613
+ * MySQL error 1046 (`ER_NO_DB_ERROR: No database selected`) is now retryable as a `ConnectionFailed` exception
567
614
 
568
- * Fixes `validates_associated` raising an exception when configured with a
569
- singular association and having `index_nested_attribute_errors` enabled.
615
+ *Clay Harmon*
570
616
 
571
- *Martin Spickermann*
572
617
 
573
- * The constant `ActiveRecord::ImmutableRelation` has been deprecated because
574
- we want to reserve that name for a stronger sense of "immutable relation".
575
- Please use `ActiveRecord::UnmodifiableRelation` instead.
618
+ ## Rails 8.1.3.1 (July 29, 2026) ##
576
619
 
577
- *Xavier Noria*
620
+ * No changes.
578
621
 
579
- * Add condensed `#inspect` for `ConnectionPool`, `AbstractAdapter`, and
580
- `DatabaseConfig`.
581
622
 
582
- *Hartley McGuire*
623
+ ## Rails 8.1.3 (March 24, 2026) ##
583
624
 
584
- * Fixed a memory performance issue in Active Record attribute methods definition.
625
+ * Fix `insert_all` and `upsert_all` log message when called on anonymous classes.
585
626
 
586
- *Jean Boussier*
627
+ *Gabriel Sobrinho*
587
628
 
588
- * Define the new Active Support notification event `start_transaction.active_record`.
629
+ * Respect `ActiveRecord::SchemaDumper.ignore_tables` when dumping SQLite virtual tables.
589
630
 
590
- This event is fired when database transactions or savepoints start, and
591
- complements `transaction.active_record`, which is emitted when they finish.
631
+ *Hans Schnedlitz*
592
632
 
593
- The payload has the transaction (`:transaction`) and the connection (`:connection`).
633
+ * Restore previous instrumenter after `execute_or_skip`
594
634
 
595
- *Xavier Noria*
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.
596
642
 
597
- * Fix an issue where the IDs reader method did not return expected results
598
- for preloaded associations in models using composite primary keys.
643
+ *Rosa Gutierrez*
599
644
 
600
- *Jay Ang*
645
+ * Bump the minimum PostgreSQL version to 9.5, due to usage of `array_position` function.
601
646
 
602
- * The payload of `sql.active_record` Active Support notifications now has the current transaction in the `:transaction` key.
647
+ *Ivan Kuchin*
603
648
 
604
- *Xavier Noria*
649
+ * Fix Ruby 4.0 delegator warning when calling inspect on ActiveRecord::Type::Serialized.
605
650
 
606
- * The payload of `transaction.active_record` Active Support notifications now has the transaction the event is related to in the `:transaction` key.
651
+ *Hammad Khan*
607
652
 
608
- *Xavier Noria*
653
+ * Fix support for table names containing hyphens.
609
654
 
610
- * 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.
655
+ *Evgeniy Demin*
611
656
 
612
- *Xavier Noria*
657
+ * Fix column deduplication for SQLite3 and PostgreSQL virtual (generated) columns.
613
658
 
614
- * Fix inference of association model on nested models with the same demodularized name.
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.
615
665
 
616
- E.g. with the following setup:
666
+ *Jay Huber*
617
667
 
618
- ```ruby
619
- class Nested::Post < ApplicationRecord
620
- has_one :post, through: :other
621
- end
622
- ```
668
+ * Fix PostgreSQL schema dumping to handle schema-qualified table names in foreign_key references that span different schemas.
623
669
 
624
- Before, `#post` would infer the model as `Nested::Post`, but now it correctly infers `Post`.
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
625
673
 
626
- *Joshua Young*
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"
627
677
 
628
- * PostgreSQL `Cidr#change?` detects the address prefix change.
678
+ *Chiperific*
629
679
 
630
- *Taketo Takashima*
631
680
 
632
- * Change `BatchEnumerator#destroy_all` to return the total number of affected rows.
681
+ ## Rails 8.1.2.1 (March 23, 2026) ##
633
682
 
634
- Previously, it always returned `nil`.
683
+ * No changes.
635
684
 
636
- *fatkodima*
637
685
 
638
- * Support `touch_all` in batches.
686
+ ## Rails 8.1.2 (January 08, 2026) ##
639
687
 
640
- ```ruby
641
- Post.in_batches.touch_all
642
- ```
688
+ * Fix counting cached queries in `ActiveRecord::RuntimeRegistry`.
643
689
 
644
690
  *fatkodima*
645
691
 
646
- * Add support for `:if_not_exists` and `:force` options to `create_schema`.
692
+ * Fix merging relations with arel equality predicates with null relations.
647
693
 
648
694
  *fatkodima*
649
695
 
650
- * Fix `index_errors` having incorrect index in association validation errors.
696
+ * Fix SQLite3 schema dump for non-autoincrement integer primary keys.
651
697
 
652
- *lulalala*
698
+ Previously, `schema.rb` should incorrectly restore that table with an auto incrementing
699
+ primary key.
653
700
 
654
- * Add `index_errors: :nested_attributes_order` mode.
701
+ *Chris Hasiński*
655
702
 
656
- 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.
703
+ * Fix PostgreSQL `schema_search_path` not being reapplied after `reset!` or `reconnect!`.
657
704
 
658
- *lulalala*
705
+ The `schema_search_path` configured in `database.yml` is now correctly
706
+ reapplied instead of falling back to PostgreSQL defaults.
659
707
 
660
- * Add `Rails.application.config.active_record.postgresql_adapter_decode_dates` to opt out of decoding dates automatically with the postgresql adapter. Defaults to true.
708
+ *Tobias Egli*
661
709
 
662
- *Joé Dupuis*
710
+ * Restore the ability of enum to be foats.
663
711
 
664
- * Association option `query_constraints` is deprecated in favor of `foreign_key`.
712
+ ```ruby
713
+ enum :rating, { low: 0.0, medium: 0.5, high: 1.0 },
714
+ ```
665
715
 
666
- *Nikita Vasilevsky*
716
+ In Rails 8.1.0, enum values are eagerly validated, and floats weren't expected.
667
717
 
668
- * Add `ENV["SKIP_TEST_DATABASE_TRUNCATE"]` flag to speed up multi-process test runs on large DBs when all tests run within default transaction.
718
+ *Said Kaldybaev*
669
719
 
670
- This cuts ~10s from the test run of HEY when run by 24 processes against the 178 tables, since ~4,000 table truncates can then be skipped.
720
+ * Ensure batched preloaded associations accounts for klass when grouping to avoid issues with STI.
671
721
 
672
- *DHH*
722
+ *zzak*, *Stjepan Hadjic*
673
723
 
674
- * Added support for recursive common table expressions.
724
+ * Fix `ActiveRecord::SoleRecordExceeded#record` to return the relation.
675
725
 
676
- ```ruby
677
- Post.with_recursive(
678
- post_and_replies: [
679
- Post.where(id: 42),
680
- Post.joins('JOIN post_and_replies ON posts.in_reply_to_id = post_and_replies.id'),
681
- ]
682
- )
683
- ```
726
+ This was the case until Rails 7.2, but starting from 8.0 it
727
+ started mistakenly returning the model class.
684
728
 
685
- Generates the following SQL:
729
+ *Jean Boussier*
686
730
 
687
- ```sql
688
- WITH RECURSIVE "post_and_replies" AS (
689
- (SELECT "posts".* FROM "posts" WHERE "posts"."id" = 42)
690
- UNION ALL
691
- (SELECT "posts".* FROM "posts" JOIN post_and_replies ON posts.in_reply_to_id = post_and_replies.id)
692
- )
693
- SELECT "posts".* FROM "posts"
694
- ```
731
+ * Improve PostgreSQLAdapter resilience to Timeout.timeout.
695
732
 
696
- *ClearlyClaire*
733
+ Better handle asynchronous exceptions being thrown inside
734
+ the `reconnect!` method.
697
735
 
698
- * `validate_constraint` can be called in a `change_table` block.
736
+ This may fixes some deep errors such as:
699
737
 
700
- ex:
701
- ```ruby
702
- change_table :products do |t|
703
- t.check_constraint "price > discounted_price", name: "price_check", validate: false
704
- t.validate_check_constraint "price_check"
705
- end
738
+ ```
739
+ undefined method `key?' for nil:NilClass (NoMethodError)
740
+ if !type_map.key?(oid)
706
741
  ```
707
742
 
708
- *Cody Cutrer*
743
+ *Jean Boussier*
709
744
 
710
- * `PostgreSQLAdapter` now decodes columns of type date to `Date` instead of string.
745
+ * Fix structured events for Active Record was not being emitted.
711
746
 
712
- Ex:
713
- ```ruby
714
- ActiveRecord::Base.connection
715
- .select_value("select '2024-01-01'::date").class #=> Date
716
- ```
747
+ *Yuji Yaginuma*
717
748
 
718
- *Joé Dupuis*
749
+ * Fix `eager_load` when loading `has_many` assocations with composite primary keys.
719
750
 
720
- * Strict loading using `:n_plus_one_only` does not eagerly load child associations.
751
+ This would result in some records being loaded multiple times.
721
752
 
722
- With this change, child associations are no longer eagerly loaded, to
723
- match intended behavior and to prevent non-deterministic order issues caused
724
- by calling methods like `first` or `last`. As `first` and `last` don't cause
725
- an N+1 by themselves, calling child associations will no longer raise.
726
- Fixes #49473.
753
+ *Martin-Alexander*
727
754
 
728
- Before:
729
755
 
730
- ```ruby
731
- person = Person.find(1)
732
- person.strict_loading!(mode: :n_plus_one_only)
733
- person.posts.first
734
- # SELECT * FROM posts WHERE person_id = 1; -- non-deterministic order
735
- person.posts.first.firm # raises ActiveRecord::StrictLoadingViolationError
736
- ```
756
+ ## Rails 8.1.1 (October 28, 2025) ##
737
757
 
738
- After:
758
+ * No changes.
739
759
 
740
- ```ruby
741
- person = Person.find(1)
742
- person.strict_loading!(mode: :n_plus_one_only)
743
- person.posts.first # this is 1+1, not N+1
744
- # SELECT * FROM posts WHERE person_id = 1 ORDER BY id LIMIT 1;
745
- person.posts.first.firm # no longer raises
746
- ```
747
760
 
748
- *Reid Lynch*
761
+ ## Rails 8.1.0 (October 22, 2025) ##
749
762
 
750
- * Allow `Sqlite3Adapter` to use `sqlite3` gem version `2.x`.
763
+ * Fix SQLite3 data loss during table alterations with CASCADE foreign keys.
751
764
 
752
- *Mike Dalessio*
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.
753
770
 
754
- * Allow `ActiveRecord::Base#pluck` to accept hash values.
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.
755
776
 
756
- ```ruby
757
- # Before
758
- Post.joins(:comments).pluck("posts.id", "comments.id", "comments.body")
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.
759
782
 
760
- # After
761
- Post.joins(:comments).pluck(posts: [:id], comments: [:id, :body])
762
- ```
783
+ *Ruy Rocha*
763
784
 
764
- *fatkodima*
785
+ * Add replicas to test database parallelization setup.
765
786
 
766
- * Raise an `ActiveRecord::ActiveRecordError` error when the MySQL database returns an invalid version string.
787
+ Setup and configuration of databases for parallel testing now includes replicas.
767
788
 
768
- *Kevin McPhillips*
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}`.
769
793
 
770
- * `ActiveRecord::Base.transaction` now yields an `ActiveRecord::Transaction` object.
794
+ *Adam Maas*
771
795
 
772
- This allows to register callbacks on it.
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+.
773
800
 
774
801
  ```ruby
775
- Article.transaction do |transaction|
776
- article.update(published: true)
777
- transaction.after_commit do
778
- PublishNotificationMailer.with(article: article).deliver_later
779
- end
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)"
780
806
  end
781
807
  ```
782
808
 
783
- *Jean Boussier*
784
-
785
- * Add `ActiveRecord::Base.current_transaction`.
809
+ *Yasuo Honda*
786
810
 
787
- Returns the current transaction, to allow registering callbacks on it.
811
+ * Optimize schema dumping to prevent duplicate file generation.
788
812
 
789
- ```ruby
790
- Article.current_transaction.after_commit do
791
- PublishNotificationMailer.with(article: article).deliver_later
792
- end
793
- ```
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.
794
817
 
795
- *Jean Boussier*
818
+ *Mikey Gough*, *Hartley McGuire*
796
819
 
797
- * Add `ActiveRecord.after_all_transactions_commit` callback.
820
+ * Add structured events for Active Record:
821
+ - `active_record.strict_loading_violation`
822
+ - `active_record.sql`
798
823
 
799
- Useful for code that may run either inside or outside a transaction and needs
800
- to perform work after the state changes have been properly persisted.
824
+ *Gannon McGibbon*
801
825
 
826
+ * Add support for integer shard keys.
802
827
  ```ruby
803
- def publish_article(article)
804
- article.update(published: true)
805
- ActiveRecord.after_all_transactions_commit do
806
- PublishNotificationMailer.with(article: article).deliver_later
807
- end
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
+ # ..
808
836
  end
809
837
  ```
810
838
 
811
- In the above example, the block is either executed immediately if called outside
812
- of a transaction, or called after the open transaction is committed.
839
+ *Nony Dutton*
813
840
 
814
- If the transaction is rolled back, the block isn't called.
841
+ * Add `ActiveRecord::Base.only_columns`
815
842
 
816
- *Jean Boussier*
843
+ Similar in use case to `ignored_columns` but listing columns to consider rather than the ones
844
+ to ignore.
817
845
 
818
- * Add the ability to ignore counter cache columns until they are backfilled.
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.
819
848
 
820
- Starting to use counter caches on existing large tables can be troublesome, because the column
821
- values must be backfilled separately of the column addition (to not lock the table for too long)
822
- and before the use of `:counter_cache` (otherwise methods like `size`/`any?`/etc, which use
823
- counter caches internally, can produce incorrect results). People usually use database triggers
824
- or callbacks on child associations while backfilling before introducing a counter cache
825
- configuration to the association.
849
+ *Anton Kandratski*
826
850
 
827
- Now, to safely backfill the column, while keeping the column updated with child records added/removed, use:
851
+ * Use `PG::Connection#close_prepared` (protocol level Close) to deallocate
852
+ prepared statements when available.
828
853
 
829
- ```ruby
830
- class Comment < ApplicationRecord
831
- belongs_to :post, counter_cache: { active: false }
832
- end
833
- ```
854
+ To enable its use, you must have pg >= 1.6.0, libpq >= 17, and a PostgreSQL
855
+ database version >= 17.
834
856
 
835
- While the counter cache is not "active", the methods like `size`/`any?`/etc will not use it,
836
- but get the results directly from the database. After the counter cache column is backfilled, simply
837
- remove the `{ active: false }` part from the counter cache definition, and it will now be used by the
838
- mentioned methods.
857
+ *Hartley McGuire*, *Andrew Jackson*
839
858
 
840
- *fatkodima*
859
+ * Fix query cache for pinned connections in multi threaded transactional tests
841
860
 
842
- * Retry known idempotent SELECT queries on connection-related exceptions.
861
+ When a pinned connection is used across separate threads, they now use a separate cache store
862
+ for each thread.
843
863
 
844
- SELECT queries we construct by walking the Arel tree and / or with known model attributes
845
- are idempotent and can safely be retried in the case of a connection error. Previously,
846
- adapters such as `TrilogyAdapter` would raise `ActiveRecord::ConnectionFailed: Trilogy::EOFError`
847
- when encountering a connection error mid-request.
864
+ This improve accuracy of system tests, and any test using multiple threads.
848
865
 
849
- *Adrianna Chang*
866
+ *Heinrich Lee Yu*, *Jean Boussier*
850
867
 
851
- * Allow association's `foreign_key` to be composite.
868
+ * Fix time attribute dirty tracking with timezone conversions.
852
869
 
853
- `query_constraints` option was the only way to configure a composite foreign key by passing an `Array`.
854
- Now it's possible to pass an Array value as `foreign_key` to achieve the same behavior of an association.
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.
855
872
 
856
- *Nikita Vasilevsky*
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.
857
875
 
858
- * Allow association's `primary_key` to be composite.
876
+ *Prateek Choudhary*
859
877
 
860
- Association's `primary_key` can be composite when derived from associated model `primary_key` or `query_constraints`.
861
- Now it's possible to explicitly set it as composite on the association.
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.
862
881
 
863
- *Nikita Vasilevsky*
882
+ *Yasuo Honda*, *Lars Kanis*
864
883
 
865
- * Add `config.active_record.permanent_connection_checkout` setting.
884
+ * Don't add `id_value` attribute alias when attribute/column with that name already exists.
866
885
 
867
- Controls whether `ActiveRecord::Base.connection` raises an error, emits a deprecation warning, or neither.
886
+ *Rob Lewis*
868
887
 
869
- `ActiveRecord::Base.connection` checkouts a database connection from the pool and keeps it leased until the end of
870
- the request or job. This behavior can be undesirable in environments that use many more threads or fibers than there
871
- is available connections.
888
+ * Remove deprecated `:unsigned_float` and `:unsigned_decimal` column methods for MySQL.
872
889
 
873
- This configuration can be used to track down and eliminate code that calls `ActiveRecord::Base.connection` and
874
- migrate it to use `ActiveRecord::Base.with_connection` instead.
890
+ *Rafael Mendonça França*
875
891
 
876
- The default behavior remains unchanged, and there is currently no plans to change the default.
892
+ * Remove deprecated `:retries` option for the SQLite3 adapter.
877
893
 
878
- *Jean Boussier*
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.
879
898
 
880
- * Add dirties option to uncached.
899
+ There are no changes to default behavior, but these allow for more specific
900
+ control over pool behavior.
881
901
 
882
- This adds a `dirties` option to `ActiveRecord::Base.uncached` and
883
- `ActiveRecord::ConnectionAdapters::ConnectionPool#uncached`.
902
+ *Matthew Draper*, *Chris AtLee*, *Rachael Wright-Munn*
884
903
 
885
- When set to `true` (the default), writes will clear all query caches belonging to the current thread.
886
- When set to `false`, writes to the affected connection pool will not clear any query cache.
904
+ * Move `LIMIT` validation from query generation to when `limit()` is called.
887
905
 
888
- This is needed by Solid Cache so that cache writes do not clear query caches.
906
+ *Hartley McGuire*, *Shuyang*
889
907
 
890
- *Donal McBreen*
908
+ * Add `ActiveRecord::CheckViolation` error class for check constraint violations.
891
909
 
892
- * Deprecate `ActiveRecord::Base.connection` in favor of `.lease_connection`.
910
+ *Ryuta Kamizono*
893
911
 
894
- The method has been renamed as `lease_connection` to better reflect that the returned
895
- connection will be held for the duration of the request or job.
912
+ * Add `ActiveRecord::ExclusionViolation` error class for exclusion constraint violations.
896
913
 
897
- This deprecation is a soft deprecation, no warnings will be issued and there is no
898
- current plan to remove the method.
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.
899
917
 
900
- *Jean Boussier*
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.
901
921
 
902
- * Deprecate `ActiveRecord::ConnectionAdapters::ConnectionPool#connection`.
922
+ *Ryuta Kamizono*
903
923
 
904
- The method has been renamed as `lease_connection` to better reflect that the returned
905
- connection will be held for the duration of the request or job.
924
+ * Attributes filtered by `filter_attributes` will now also be filtered by `filter_parameters`
925
+ so sensitive information is not leaked.
906
926
 
907
- *Jean Boussier*
927
+ *Jill Klang*
908
928
 
909
- * Expose a generic fixture accessor for fixture names that may conflict with Minitest.
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.
910
934
 
911
935
  ```ruby
912
- assert_equal "Ruby on Rails", web_sites(:rubyonrails).name
913
- assert_equal "Ruby on Rails", fixture(:web_sites, :rubyonrails).name
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
914
955
  ```
915
956
 
916
- *Jean Boussier*
957
+ *Kir Shatrov*
917
958
 
918
- * Using `Model.query_constraints` with a single non-primary-key column used to raise as expected, but with an
919
- incorrect error message.
959
+ * Fix `#merge` with `#or` or `#and` and a mixture of attributes and SQL strings resulting in an incorrect query.
920
960
 
921
- This has been fixed to raise with a more appropriate error message.
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
+ ```
922
965
 
923
- *Joshua Young*
966
+ Before:
924
967
 
925
- * Fix `has_one` association autosave setting the foreign key attribute when it is unchanged.
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
+ ```
979
+
980
+ After:
926
981
 
927
- This behavior is also inconsistent with autosaving `belongs_to` and can have unintended side effects like raising
928
- an `ActiveRecord::ReadonlyAttributeError` when the foreign key attribute is marked as read-only.
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
+ ```
929
994
 
930
995
  *Joshua Young*
931
996
 
932
- * Remove deprecated behavior that would rollback a transaction block when exited using `return`, `break` or `throw`.
997
+ * Make schema dumper to account for `ActiveRecord.dump_schemas` when dumping in `:ruby` format.
933
998
 
934
- *Rafael Mendonça França*
999
+ *fatkodima*
935
1000
 
936
- * Deprecate `Rails.application.config.active_record.commit_transaction_on_non_local_return`.
1001
+ * Add `:touch` option to `update_column`/`update_columns` methods.
937
1002
 
938
- *Rafael Mendonça França*
1003
+ ```ruby
1004
+ # Will update :updated_at/:updated_on alongside :nice column.
1005
+ user.update_column(:nice, true, touch: true)
939
1006
 
940
- * Remove deprecated support to pass `rewhere` to `ActiveRecord::Relation#merge`.
1007
+ # Will update :updated_at/:updated_on alongside :last_ip column
1008
+ user.update_columns(last_ip: request.remote_ip, touch: true)
1009
+ ```
941
1010
 
942
- *Rafael Mendonça França*
1011
+ *Dmitrii Ivliev*
943
1012
 
944
- * Remove deprecated support to pass `deferrable: true` to `add_foreign_key`.
1013
+ * Optimize Active Record batching further when using ranges.
945
1014
 
946
- *Rafael Mendonça França*
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`).
947
1018
 
948
- * Remove deprecated support to quote `ActiveSupport::Duration`.
1019
+ *Maxime Réty*, *fatkodima*
949
1020
 
950
- *Rafael Mendonça França*
1021
+ * Include current character length in error messages for index and table name length validations.
951
1022
 
952
- * Remove deprecated `#quote_bound_value`.
1023
+ *Joshua Young*
953
1024
 
954
- *Rafael Mendonça França*
1025
+ * Add `rename_schema` method for PostgreSQL.
955
1026
 
956
- * Remove deprecated `ActiveRecord::ConnectionAdapters::ConnectionPool#connection_klass`.
1027
+ *T S Vallender*
957
1028
 
958
- *Rafael Mendonça França*
1029
+ * Implement support for deprecating associations:
959
1030
 
960
- * Remove deprecated support to apply `#connection_pool_list`, `#active_connections?`, `#clear_active_connections!`,
961
- `#clear_reloadable_connections!`, `#clear_all_connections!` and `#flush_idle_connections!` to the connections pools
962
- for the current role when the `role` argument isn't provided.
1031
+ ```ruby
1032
+ has_many :posts, deprecated: true
1033
+ ```
963
1034
 
964
- *Rafael Mendonça França*
1035
+ With that, Active Record will report any usage of the `posts` association.
965
1036
 
966
- * Remove deprecated `#all_connection_pools`.
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.
967
1040
 
968
- *Rafael Mendonça França*
1041
+ Please, check the docs for further details.
969
1042
 
970
- * Remove deprecated `ActiveRecord::ConnectionAdapters::SchemaCache#data_sources`.
1043
+ *Xavier Noria*
971
1044
 
972
- *Rafael Mendonça França*
1045
+ * PostgreSQL adapter create DB now supports `locale_provider` and `locale`.
973
1046
 
974
- * Remove deprecated `ActiveRecord::ConnectionAdapters::SchemaCache.load_from`.
1047
+ *Bengt-Ove Hollaender*
975
1048
 
976
- *Rafael Mendonça França*
1049
+ * Use ntuples to populate row_count instead of count for Postgres
977
1050
 
978
- * Remove deprecated `#all_foreign_keys_valid?` from database adapters.
1051
+ *Jonathan Calvert*
979
1052
 
980
- *Rafael Mendonça França*
1053
+ * Fix checking whether an unpersisted record is `include?`d in a strictly
1054
+ loaded `has_and_belongs_to_many` association.
981
1055
 
982
- * Remove deprecated support to passing coder and class as second argument to `serialize`.
1056
+ *Hartley McGuire*
983
1057
 
984
- *Rafael Mendonça França*
1058
+ * Add ability to change transaction isolation for all pools within a block.
985
1059
 
986
- * Remove deprecated support to `ActiveRecord::Base#read_attribute(:id)` to return the custom primary key value.
1060
+ This functionality is useful if your application needs to change the database
1061
+ transaction isolation for a request or action.
987
1062
 
988
- *Rafael Mendonça França*
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.
989
1066
 
990
- * Remove deprecated `TestFixtures.fixture_path`.
1067
+ This works with explicit and implicit transactions:
991
1068
 
992
- *Rafael Mendonça França*
1069
+ ```ruby
1070
+ ActiveRecord.with_transaction_isolation_level(:read_committed) do
1071
+ Tag.transaction do # opens a transaction explicitly
1072
+ Tag.create!
1073
+ end
1074
+ end
1075
+ ```
993
1076
 
994
- * Remove deprecated behavior to support referring to a singular association by its plural name.
1077
+ ```ruby
1078
+ ActiveRecord.with_transaction_isolation_level(:read_committed) do
1079
+ Tag.create! # opens a transaction implicitly
1080
+ end
1081
+ ```
995
1082
 
996
- *Rafael Mendonça França*
1083
+ *Eileen M. Uchitelle*
997
1084
 
998
- * Deprecate `Rails.application.config.active_record.allow_deprecated_singular_associations_name`.
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.
999
1088
 
1000
- *Rafael Mendonça França*
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.
1001
1091
 
1002
- * Remove deprecated support to passing `SchemaMigration` and `InternalMetadata` classes as arguments to
1003
- `ActiveRecord::MigrationContext`.
1092
+ ```ruby
1093
+ config.active_record.raise_on_missing_required_finder_order_columns = true
1094
+ ```
1004
1095
 
1005
- *Rafael Mendonça França*
1096
+ *Joshua Young*
1006
1097
 
1007
- * Remove deprecated `ActiveRecord::Migration.check_pending!` method.
1098
+ * `:class_name` is now invalid in polymorphic `belongs_to` associations.
1008
1099
 
1009
- *Rafael Mendonça França*
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.
1010
1102
 
1011
- * Remove deprecated `ActiveRecord::LogSubscriber.runtime` method.
1103
+ Existing polymorphic associations setting this option can just delete it.
1104
+ While it did not raise, it had no effect anyway.
1012
1105
 
1013
- *Rafael Mendonça França*
1106
+ *Xavier Noria*
1014
1107
 
1015
- * Remove deprecated `ActiveRecord::LogSubscriber.runtime=` method.
1108
+ * Add support for multiple databases to `db:migrate:reset`.
1016
1109
 
1017
- *Rafael Mendonça França*
1110
+ *Joé Dupuis*
1018
1111
 
1019
- * Remove deprecated `ActiveRecord::LogSubscriber.reset_runtime` method.
1112
+ * Add `affected_rows` to `ActiveRecord::Result`.
1020
1113
 
1021
- *Rafael Mendonça França*
1114
+ *Jenny Shen*
1022
1115
 
1023
- * Remove deprecated support to define `explain` in the connection adapter with 2 arguments.
1116
+ * Enable passing retryable SqlLiterals to `#where`.
1024
1117
 
1025
- *Rafael Mendonça França*
1118
+ *Hartley McGuire*
1026
1119
 
1027
- * Remove deprecated `ActiveRecord::ActiveJobRequiredError`.
1120
+ * Set default for primary keys in `insert_all`/`upsert_all`.
1028
1121
 
1029
- *Rafael Mendonça França*
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.
1030
1125
 
1031
- * Remove deprecated `ActiveRecord::Base.clear_active_connections!`.
1126
+ *Jenny Shen*
1032
1127
 
1033
- *Rafael Mendonça França*
1128
+ * Add a load hook `active_record_database_configurations` for `ActiveRecord::DatabaseConfigurations`
1034
1129
 
1035
- * Remove deprecated `ActiveRecord::Base.clear_reloadable_connections!`.
1130
+ *Mike Dalessio*
1036
1131
 
1037
- *Rafael Mendonça França*
1132
+ * Use `TRUE` and `FALSE` for SQLite queries with boolean columns.
1038
1133
 
1039
- * Remove deprecated `ActiveRecord::Base.clear_all_connections!`.
1134
+ *Hartley McGuire*
1040
1135
 
1041
- *Rafael Mendonça França*
1136
+ * Bump minimum supported SQLite to 3.23.0.
1042
1137
 
1043
- * Remove deprecated `ActiveRecord::Base.flush_idle_connections!`.
1138
+ *Hartley McGuire*
1044
1139
 
1045
- *Rafael Mendonça França*
1140
+ * Allow allocated Active Records to lookup associations.
1046
1141
 
1047
- * Remove deprecated `name` argument from `ActiveRecord::Base.remove_connection`.
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.
1048
1145
 
1049
- *Rafael Mendonça França*
1146
+ *Gannon McGibbon*
1050
1147
 
1051
- * Remove deprecated support to call `alias_attribute` with non-existent attribute names.
1148
+ * Encryption now supports `support_unencrypted_data: true` being set per-attribute.
1052
1149
 
1053
- *Rafael Mendonça França*
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.
1054
1152
 
1055
- * Remove deprecated `Rails.application.config.active_record.suppress_multiple_database_warning`.
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
1158
+ end
1159
+ ```
1056
1160
 
1057
- *Rafael Mendonça França*
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
1166
+ end
1167
+ ```
1058
1168
 
1059
- * Add `ActiveRecord::Encryption::MessagePackMessageSerializer`.
1169
+ *Alex Ghiculescu*
1060
1170
 
1061
- Serialize data to the MessagePack format, for efficient storage in binary columns.
1171
+ * Model generator no longer needs a database connection to validate column types.
1062
1172
 
1063
- The binary encoding requires around 30% less space than the base64 encoding
1064
- used by the default serializer.
1173
+ *Mike Dalessio*
1065
1174
 
1066
- *Donal McBreen*
1175
+ * Allow signed ID verifiers to be configurable via `Rails.application.message_verifiers`
1067
1176
 
1068
- * Add support for encrypting binary columns.
1177
+ Prior to this change, the primary way to configure signed ID verifiers was
1178
+ to set `signed_id_verifier` on each model class:
1069
1179
 
1070
- Ensure encryption and decryption pass `Type::Binary::Data` around for binary data.
1180
+ ```ruby
1181
+ Post.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
1182
+ Comment.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
1183
+ ```
1071
1184
 
1072
- Previously encrypting binary columns with the `ActiveRecord::Encryption::MessageSerializer`
1073
- incidentally worked for MySQL and SQLite, but not PostgreSQL.
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:
1074
1188
 
1075
- *Donal McBreen*
1189
+ ```ruby
1190
+ { digest: "SHA256", serializer: JSON, url_safe: true }
1191
+ ```
1076
1192
 
1077
- * Deprecated `ENV["SCHEMA_CACHE"]` in favor of `schema_cache_path` in the database configuration.
1193
+ Thus it was cumbersome to rotate configuration for all verifiers.
1078
1194
 
1079
- *Rafael Mendonça França*
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.
1080
1202
 
1081
- * Add `ActiveRecord::Base.with_connection` as a shortcut for leasing a connection for a short duration.
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:
1082
1208
 
1083
- The leased connection is yielded, and for the duration of the block, any call to `ActiveRecord::Base.connection`
1084
- will yield that same connection.
1209
+ ```ruby
1210
+ # BEFORE
1211
+ Post.signed_id_verifier_secret = "my secret"
1085
1212
 
1086
- This is useful to perform a few database operations without causing a connection to be leased for the
1087
- entire duration of the request or job.
1213
+ # AFTER
1214
+ Post.signed_id_verifier = ActiveSupport::MessageVerifier.new("my secret", digest: "SHA256", serializer: JSON, url_safe: true)
1215
+ ```
1088
1216
 
1089
- *Jean Boussier*
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_:
1090
1220
 
1091
- * Deprecate `config.active_record.warn_on_records_fetched_greater_than` now that `sql.active_record`
1092
- notification includes `:row_count` field.
1221
+ ```ruby
1222
+ # BEFORE
1223
+ ActiveRecord::Base.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
1224
+ Post.signed_id_verifier == ActiveRecord::Base.signed_id_verifier # => false
1093
1225
 
1094
- *Jason Nochlin*
1226
+ # AFTER
1227
+ ActiveRecord::Base.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
1228
+ Post.signed_id_verifier == ActiveRecord::Base.signed_id_verifier # => true
1095
1229
 
1096
- * Fix an issue with `where.associated` losing the current join type scope.
1230
+ Post.signed_id_verifier_secret = "my secret" # => deprecation warning
1231
+ Post.signed_id_verifier == ActiveRecord::Base.signed_id_verifier # => false
1232
+ ```
1097
1233
 
1098
- Example:
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:
1099
1238
 
1100
- ```ruby
1101
- Post.left_joins(:author).where.associated(:author)
1102
- ```
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", ...)
1103
1243
 
1104
- Previously, the `LEFT OUTER JOIN` would be lost and converted to an `INNER JOIN`.
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
+ ```
1105
1250
 
1106
- *Saleh Alhaddad*
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
1107
1252
 
1108
- * Fix an issue where `ActiveRecord::Encryption` configurations are not ready before the loading
1109
- of Active Record models, when an application is eager loaded. As a result, encrypted attributes
1110
- could be misconfigured in some cases.
1253
+ *Ali Sepehri*, *Jonathan Hefner*
1111
1254
 
1112
- *Maxime Réty*
1255
+ * Prepend `extra_flags` in postgres' `structure_load`
1113
1256
 
1114
- * Deprecate defining an `enum` with keyword arguments.
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.
1115
1260
 
1116
- ```ruby
1117
- class Function > ApplicationRecord
1118
- # BAD
1119
- enum color: [:red, :blue],
1120
- type: [:instance, :class]
1121
-
1122
- # GOOD
1123
- enum :color, [:red, :blue]
1124
- enum :type, [:instance, :class]
1125
- end
1126
- ```
1261
+ *Alice Loeser*
1127
1262
 
1128
- *Hartley McGuire*
1263
+ * Allow bypassing primary key/constraint addition in `implicit_order_column`
1129
1264
 
1130
- * Add `config.active_record.validate_migration_timestamps` option for validating migration timestamps.
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.
1131
1270
 
1132
- When set, validates that the timestamp prefix for a migration is no more than a day ahead of
1133
- the timestamp associated with the current time. This is designed to prevent migrations prefixes
1134
- from being hand-edited to future timestamps, which impacts migration generation and other
1135
- migration commands.
1271
+ *Issy Long*
1136
1272
 
1137
- *Adrianna Chang*
1273
+ * Allow setting the `schema_format` via database configuration.
1138
1274
 
1139
- * Properly synchronize `Mysql2Adapter#active?` and `TrilogyAdapter#active?`.
1275
+ ```
1276
+ primary:
1277
+ schema_format: ruby
1278
+ ```
1140
1279
 
1141
- As well as `disconnect!` and `verify!`.
1280
+ Useful for multi-database setups when apps require different formats per-database.
1142
1281
 
1143
- This generally isn't a big problem as connections must not be shared between
1144
- threads, but is required when running transactional tests or system tests
1145
- and could lead to a SEGV.
1282
+ *T S Vallender*
1146
1283
 
1147
- *Jean Boussier*
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.
1148
1292
 
1149
- * Support `:source_location` tag option for query log tags.
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:
1150
1299
 
1151
1300
  ```ruby
1152
- config.active_record.query_log_tags << :source_location
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
1317
+ end
1153
1318
  ```
1154
1319
 
1155
- Calculating the caller location is a costly operation and should be used primarily in development
1156
- (note, there is also a `config.active_record.verbose_query_logs` that serves the same purpose)
1157
- or occasionally on production for debugging purposes.
1320
+ *Merve Taner*
1158
1321
 
1159
- *fatkodima*
1322
+ * Respect `implicit_order_column` in `ActiveRecord::Relation#reverse_order`.
1160
1323
 
1161
- * Add an option to `ActiveRecord::Encryption::Encryptor` to disable compression.
1324
+ *Joshua Young*
1162
1325
 
1163
- Allow compression to be disabled by setting `compress: false`
1326
+ * Add column types to `ActiveRecord::Result` for SQLite3.
1164
1327
 
1165
- ```ruby
1166
- class User
1167
- encrypts :name, encryptor: ActiveRecord::Encryption::Encryptor.new(compress: false)
1168
- end
1169
- ```
1328
+ *Andrew Kane*
1170
1329
 
1171
- *Donal McBreen*
1330
+ * Raise `ActiveRecord::ReadOnlyError` when pessimistically locking with a readonly role.
1172
1331
 
1173
- * Deprecate passing strings to `ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename`.
1332
+ *Joshua Young*
1174
1333
 
1175
- A `ActiveRecord::DatabaseConfigurations::DatabaseConfig` object should be passed instead.
1334
+ * Fix using the `SQLite3Adapter`'s `dbconsole` method outside of a Rails application.
1176
1335
 
1177
- *Rafael Mendonça França*
1336
+ *Hartley McGuire*
1178
1337
 
1179
- * Add `row_count` field to `sql.active_record` notification.
1338
+ * Fix migrating multiple databases with `ActiveRecord::PendingMigration` action.
1180
1339
 
1181
- This field returns the amount of rows returned by the query that emitted the notification.
1340
+ *Gannon McGibbon*
1182
1341
 
1183
- This metric is useful in cases where one wants to detect queries with big result sets.
1342
+ * Enable automatically retrying idempotent association queries on connection
1343
+ errors.
1184
1344
 
1185
- *Marvin Bitterlich*
1345
+ *Hartley McGuire*
1186
1346
 
1187
- * Consistently raise an `ArgumentError` when passing an invalid argument to a nested attributes association writer.
1347
+ * Add `allow_retry` to `sql.active_record` instrumentation.
1188
1348
 
1189
- Previously, this would only raise on collection associations and produce a generic error on singular associations.
1349
+ This enables identifying queries which queries are automatically retryable on connection errors.
1190
1350
 
1191
- Now, it will raise on both collection and singular associations.
1351
+ *Hartley McGuire*
1192
1352
 
1193
- *Joshua Young*
1353
+ * Better support UPDATE with JOIN for Postgresql and SQLite3
1194
1354
 
1195
- * Fix single quote escapes on default generated MySQL columns.
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:
1196
1358
 
1197
- MySQL 5.7.5+ supports generated columns, which can be used to create a column that is computed from an expression.
1359
+ ```ruby
1360
+ Comment.joins(:post).update_all("title = posts.title")
1361
+ ```
1198
1362
 
1199
- Previously, the schema dump would output a string with double escapes for generated columns with single quotes in the default expression.
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.
1200
1365
 
1201
- This would result in issues when importing the schema on a fresh instance of a MySQL database.
1366
+ *Jean Boussier*
1202
1367
 
1203
- Now, the string will not be escaped and will be valid Ruby upon importing of the schema.
1368
+ * Introduce a before-fork hook in `ActiveSupport::Testing::Parallelization` to clear existing
1369
+ connections, to avoid fork-safety issues with the mysql2 adapter.
1204
1370
 
1205
- *Yash Kapadia*
1371
+ Fixes #41776
1206
1372
 
1207
- * Fix Migrations with versions older than 7.1 validating options given to
1208
- `add_reference` and `t.references`.
1373
+ *Mike Dalessio*, *Donal McBreen*
1209
1374
 
1210
- *Hartley McGuire*
1375
+ * PoolConfig no longer keeps a reference to the connection class.
1211
1376
 
1212
- * Add `<role>_types` class method to `ActiveRecord::DelegatedType` so that the delegated types can be introspected.
1377
+ Keeping a reference to the class caused subtle issues when combined with reloading in
1378
+ development. Fixes #54343.
1213
1379
 
1214
- *JP Rosevear*
1380
+ *Mike Dalessio*
1215
1381
 
1216
- * Make `schema_dump`, `query_cache`, `replica` and `database_tasks` configurable via `DATABASE_URL`.
1382
+ * Fix SQL notifications sometimes not sent when using async queries.
1217
1383
 
1218
- This wouldn't always work previously because boolean values would be interpreted as strings.
1384
+ ```ruby
1385
+ Post.async_count
1386
+ ActiveSupport::Notifications.subscribed(->(*) { "Will never reach here" }) do
1387
+ Post.count
1388
+ end
1389
+ ```
1219
1390
 
1220
- e.g. `DATABASE_URL=postgres://localhost/foo?schema_dump=false` now properly disable dumping the schema
1221
- cache.
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.
1222
1394
 
1223
- *Mike Coutermarsh*, *Jean Boussier*
1395
+ *Edouard Chin*
1224
1396
 
1225
- * Introduce `ActiveRecord::Transactions::ClassMethods#set_callback`.
1397
+ * Eliminate queries loading dumped schema cache on Postgres
1226
1398
 
1227
- It is identical to `ActiveSupport::Callbacks::ClassMethods#set_callback`
1228
- but with support for `after_commit` and `after_rollback` callback options.
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.
1229
1402
 
1230
- *Joshua Young*
1403
+ *James Coleman*
1231
1404
 
1232
- * Make `ActiveRecord::Encryption::Encryptor` agnostic of the serialization format used for encrypted data.
1405
+ * `ActiveRecord::Coder::JSON` can be instantiated
1233
1406
 
1234
- Previously, the encryptor instance only allowed an encrypted value serialized as a `String` to be passed to the message serializer.
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)
1410
+ ```
1411
+ *matthaigh27*
1235
1412
 
1236
- Now, the encryptor lets the configured `message_serializer` decide which types of serialized encrypted values are supported. A custom serialiser is therefore allowed to serialize `ActiveRecord::Encryption::Message` objects using a type other than `String`.
1413
+ * Deprecate using `insert_all`/`upsert_all` with unpersisted records in associations.
1237
1414
 
1238
- The default `ActiveRecord::Encryption::MessageSerializer` already ensures that only `String` objects are passed for deserialization.
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.
1239
1418
 
1240
- *Maxime Réty*
1419
+ *Nick Schwaderer*
1241
1420
 
1242
- * Fix `encrypted_attribute?` to take into account context properties passed to `encrypts`.
1421
+ * Make column name optional for `index_exists?`.
1243
1422
 
1244
- *Maxime Réty*
1423
+ This aligns well with `remove_index` signature as well, where
1424
+ index name doesn't need to be derived from the column names.
1245
1425
 
1246
- * The object returned by `explain` now responds to `pluck`, `first`,
1247
- `last`, `average`, `count`, `maximum`, `minimum`, and `sum`. Those
1248
- new methods run `EXPLAIN` on the corresponding queries:
1426
+ *Ali Ismayiliov*
1249
1427
 
1250
- ```ruby
1251
- User.all.explain.count
1252
- # EXPLAIN SELECT COUNT(*) FROM `users`
1253
- # ...
1428
+ * Change the payload name of `sql.active_record` notification for eager
1429
+ loading from "SQL" to "#{model.name} Eager Load".
1254
1430
 
1255
- User.all.explain.maximum(:id)
1256
- # EXPLAIN SELECT MAX(`users`.`id`) FROM `users`
1257
- # ...
1258
- ```
1431
+ *zzak*
1259
1432
 
1260
- *Petrik de Heus*
1433
+ * Enable automatically retrying idempotent `#exists?` queries on connection
1434
+ errors.
1261
1435
 
1262
- * Fixes an issue where `validates_associated` `:on` option wasn't respected
1263
- when validating associated records.
1436
+ *Hartley McGuire*, *classidied*
1264
1437
 
1265
- *Austen Madden*, *Alex Ghiculescu*, *Rafał Brize*
1438
+ * Deprecate usage of unsupported methods in conjunction with `update_all`:
1266
1439
 
1267
- * Allow overriding SQLite defaults from `database.yml`.
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.
1268
1443
 
1269
- Any PRAGMA configuration set under the `pragmas` key in the configuration
1270
- file takes precedence over Rails' defaults, and additional PRAGMAs can be
1271
- set as well.
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.
1272
1446
 
1273
- ```yaml
1274
- database: storage/development.sqlite3
1275
- timeout: 5000
1276
- pragmas:
1277
- journal_mode: off
1278
- temp_store: memory
1279
- ```
1447
+ *Edouard Chin*
1280
1448
 
1281
- *Stephen Margheim*
1449
+ * The table columns inside `schema.rb` are now sorted alphabetically.
1282
1450
 
1283
- * Remove warning message when running SQLite in production, but leave it unconfigured.
1451
+ Previously they'd be sorted by creation order, which can cause merge conflicts when two
1452
+ branches modify the same table concurrently.
1284
1453
 
1285
- There are valid use cases for running SQLite in production. However, it must be done
1286
- with care, so instead of a warning most users won't see anyway, it's preferable to
1287
- leave the configuration commented out to force them to think about having the database
1288
- on a persistent volume etc.
1454
+ *John Duff*
1289
1455
 
1290
- *Jacopo Beschi*, *Jean Boussier*
1456
+ * Introduce versions formatter for the schema dumper.
1291
1457
 
1292
- * Add support for generated columns to the SQLite3 adapter.
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.
1293
1461
 
1294
- Generated columns (both stored and dynamic) are supported since version 3.31.0 of SQLite.
1295
- This adds support for those to the SQLite3 adapter.
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.
1296
1464
 
1297
- ```ruby
1298
- create_table :users do |t|
1299
- t.string :name
1300
- t.virtual :name_upper, type: :string, as: 'UPPER(name)'
1301
- t.virtual :name_lower, type: :string, as: 'LOWER(name)', stored: true
1302
- end
1303
- ```
1465
+ *fatkodima*
1304
1466
 
1305
- *Stephen Margheim*
1467
+ * Serialized attributes can now be marked as comparable.
1306
1468
 
1307
- * TrilogyAdapter: ignore `host` if `socket` parameter is set.
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.
1308
1472
 
1309
- This allows to configure a connection on a UNIX socket via `DATABASE_URL`:
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.
1310
1476
 
1311
- ```
1312
- DATABASE_URL=trilogy://does-not-matter/my_db_production?socket=/var/run/mysql.sock
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.
1479
+
1480
+ ```ruby
1481
+ serialize :config, type: Hash, coder: JSON, comparable: true
1313
1482
  ```
1314
1483
 
1315
1484
  *Jean Boussier*
1316
1485
 
1317
- * Make `assert_queries_count`, `assert_no_queries`, `assert_queries_match`, and
1318
- `assert_no_queries_match` assertions public.
1486
+ * Fix MySQL default functions getting dropped when changing a column's nullability.
1319
1487
 
1320
- To assert the expected number of queries are made, Rails internally uses `assert_queries_count` and
1321
- `assert_no_queries`. To assert that specific SQL queries are made, `assert_queries_match` and
1322
- `assert_no_queries_match` are used. These assertions can now be used in applications as well.
1488
+ *Bastian Bartmann*
1323
1489
 
1324
- ```ruby
1325
- class ArticleTest < ActiveSupport::TestCase
1326
- test "queries are made" do
1327
- assert_queries_count(1) { Article.first }
1328
- end
1490
+ * SQLite extensions can be configured in `config/database.yml`.
1329
1491
 
1330
- test "creates a foreign key" do
1331
- assert_queries_match(/ADD FOREIGN KEY/i, include_schema: true) do
1332
- @connection.add_foreign_key(:comments, :posts)
1333
- end
1334
- end
1335
- end
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
1336
1503
  ```
1337
1504
 
1338
- *Petrik de Heus*, *fatkodima*
1505
+ *Mike Dalessio*
1339
1506
 
1340
- * Fix `has_secure_token` calls the setter method on initialize.
1507
+ * `ActiveRecord::Middleware::ShardSelector` supports granular database connection switching.
1341
1508
 
1342
- *Abeid Ahmed*
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`.
1343
1513
 
1344
- * When using a `DATABASE_URL`, allow for a configuration to map the protocol in the URL to a specific database
1345
- adapter. This allows decoupling the adapter the application chooses to use from the database connection details
1346
- set in the deployment environment.
1514
+ For example, this configuration tells `ShardSelector` to switch shards using
1515
+ `AnimalsRecord.connected_to`:
1347
1516
 
1348
- ```ruby
1349
- # ENV['DATABASE_URL'] = "mysql://localhost/example_database"
1350
- config.active_record.protocol_adapters.mysql = "trilogy"
1351
- # will connect to MySQL using the trilogy adapter
1517
+ ```
1518
+ config.active_record.shard_selector = { class_name: "AnimalsRecord" }
1352
1519
  ```
1353
1520
 
1354
- *Jean Boussier*, *Kevin McPhillips*
1521
+ *Mike Dalessio*
1355
1522
 
1356
- * In cases where MySQL returns `warning_count` greater than zero, but returns no warnings when
1357
- the `SHOW WARNINGS` query is executed, `ActiveRecord.db_warnings_action` proc will still be
1358
- called with a generic warning message rather than silently ignoring the warning(s).
1523
+ * Reset relations after `insert_all`/`upsert_all`.
1359
1524
 
1360
- *Kevin McPhillips*
1525
+ Bulk insert/upsert methods will now call `reset` if used on a relation, matching the behavior of `update_all`.
1361
1526
 
1362
- * `DatabaseConfigurations#configs_for` accepts a symbol in the `name` parameter.
1527
+ *Milo Winningham*
1363
1528
 
1364
- *Andrew Novoselac*
1529
+ * Use `_N` as a parallel tests databases suffixes
1365
1530
 
1366
- * Fix `where(field: values)` queries when `field` is a serialized attribute
1367
- (for example, when `field` uses `ActiveRecord::Base.serialize` or is a JSON
1368
- column).
1531
+ Peviously, `-N` was used as a suffix. This can cause problems for RDBMSes
1532
+ which do not support dashes in database names.
1369
1533
 
1370
- *João Alves*
1534
+ *fatkodima*
1371
1535
 
1372
- * Make the output of `ActiveRecord::Core#inspect` configurable.
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.
1373
1539
 
1374
- By default, calling `inspect` on a record will yield a formatted string including just the `id`.
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.
1375
1543
 
1376
- ```ruby
1377
- Post.first.inspect #=> "#<Post id: 1>"
1378
- ```
1544
+ *Matthew Draper*
1379
1545
 
1380
- The attributes to be included in the output of `inspect` can be configured with
1381
- `ActiveRecord::Core#attributes_for_inspect`.
1546
+ * Allow to reset cache counters for multiple records.
1382
1547
 
1383
- ```ruby
1384
- Post.attributes_for_inspect = [:id, :title]
1385
- Post.first.inspect #=> "#<Post id: 1, title: "Hello, World!">"
1386
1548
  ```
1387
-
1388
- With `attributes_for_inspect` set to `:all`, `inspect` will list all the record's attributes.
1389
-
1390
- ```ruby
1391
- Post.attributes_for_inspect = :all
1392
- Post.first.inspect #=> "#<Post id: 1, title: "Hello, World!", published_at: "2023-10-23 14:28:11 +0000">"
1549
+ Aircraft.reset_counters([1, 2, 3], :wheels_count)
1393
1550
  ```
1394
1551
 
1395
- In `development` and `test` mode, `attributes_for_inspect` will be set to `:all` by default.
1396
-
1397
- You can also call `full_inspect` to get an inspection with all the attributes.
1398
-
1399
- The attributes in `attribute_for_inspect` will also be used for `pretty_print`.
1400
-
1401
- *Andrew Novoselac*
1402
-
1403
- * Don't mark attributes as changed when reassigned to `Float::INFINITY` or
1404
- `-Float::INFINITY`.
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.
1405
1554
 
1406
- *Maicol Bentancor*
1555
+ *fatkodima*
1407
1556
 
1408
- * Support the `RETURNING` clause for MariaDB.
1557
+ * Add `affected_rows` to `sql.active_record` Notification.
1409
1558
 
1410
- *fatkodima*, *Nikolay Kondratyev*
1559
+ *Hartley McGuire*
1411
1560
 
1412
- * The SQLite3 adapter now implements the `supports_deferrable_constraints?` contract.
1561
+ * Fix `sum` when performing a grouped calculation.
1413
1562
 
1414
- Allows foreign keys to be deferred by adding the `:deferrable` key to the `foreign_key` options.
1563
+ `User.group(:friendly).sum` no longer worked. This is fixed.
1415
1564
 
1416
- ```ruby
1417
- add_reference :person, :alias, foreign_key: { deferrable: :deferred }
1418
- add_reference :alias, :person, foreign_key: { deferrable: :deferred }
1419
- ```
1565
+ *Edouard Chin*
1420
1566
 
1421
- *Stephen Margheim*
1567
+ * Add support for enabling or disabling transactional tests per database.
1422
1568
 
1423
- * Add the `set_constraints` helper to PostgreSQL connections.
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.
1424
1572
 
1425
1573
  ```ruby
1426
- Post.create!(user_id: -1) # => ActiveRecord::InvalidForeignKey
1427
-
1428
- Post.transaction do
1429
- Post.connection.set_constraints(:deferred)
1430
- p = Post.create!(user_id: -1)
1431
- u = User.create!
1432
- p.user = u
1433
- p.save!
1574
+ class MostlyTransactionalTest < ActiveSupport::TestCase
1575
+ self.use_transactional_tests = true
1576
+ skip_transactional_tests_for_database :shared
1434
1577
  end
1435
1578
  ```
1436
1579
 
1437
- *Cody Cutrer*
1438
-
1439
- * Include `ActiveModel::API` in `ActiveRecord::Base`.
1440
-
1441
- *Sean Doyle*
1580
+ *Matthew Cheetham*, *Morgan Mareve*
1442
1581
 
1443
- * Ensure `#signed_id` outputs `url_safe` strings.
1582
+ * Cast `query_cache` value when using URL configuration.
1444
1583
 
1445
- *Jason Meller*
1446
-
1447
- * Add `nulls_last` and working `desc.nulls_first` for MySQL.
1584
+ *zzak*
1448
1585
 
1449
- *Tristan Fellows*
1586
+ * NULLS NOT DISTINCT works with UNIQUE CONSTRAINT as well as UNIQUE INDEX.
1450
1587
 
1451
- * Allow for more complex hash arguments for `order` which mimics `where` in `ActiveRecord::Relation`.
1588
+ *Ryuta Kamizono*
1452
1589
 
1453
- ```ruby
1454
- Topic.includes(:posts).order(posts: { created_at: :desc })
1455
- ```
1590
+ * `PG::UnableToSend: no connection to the server` is now retryable as a connection-related exception
1456
1591
 
1457
- *Myles Boone*
1592
+ *Kazuma Watanabe*
1458
1593
 
1459
- Please check [7-1-stable](https://github.com/rails/rails/blob/7-1-stable/activerecord/CHANGELOG.md) for previous changes.
1594
+ Please check [8-0-stable](https://github.com/rails/rails/blob/8-0-stable/activerecord/CHANGELOG.md) for previous changes.