activerecord 7.2.3 → 8.1.3

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