activerecord 8.0.5.1 → 8.1.0.beta1

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 (157) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +421 -657
  3. data/README.rdoc +1 -1
  4. data/lib/active_record/association_relation.rb +1 -1
  5. data/lib/active_record/associations/association.rb +1 -1
  6. data/lib/active_record/associations/belongs_to_association.rb +0 -2
  7. data/lib/active_record/associations/builder/association.rb +16 -5
  8. data/lib/active_record/associations/builder/belongs_to.rb +17 -4
  9. data/lib/active_record/associations/builder/collection_association.rb +7 -3
  10. data/lib/active_record/associations/builder/has_one.rb +1 -1
  11. data/lib/active_record/associations/builder/singular_association.rb +33 -5
  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/errors.rb +3 -0
  15. data/lib/active_record/associations/join_dependency.rb +4 -2
  16. data/lib/active_record/associations/preloader/batch.rb +1 -7
  17. data/lib/active_record/associations/preloader/branch.rb +1 -0
  18. data/lib/active_record/associations.rb +159 -21
  19. data/lib/active_record/attribute_methods/serialization.rb +16 -3
  20. data/lib/active_record/attribute_methods.rb +1 -1
  21. data/lib/active_record/attributes.rb +3 -0
  22. data/lib/active_record/autosave_association.rb +2 -2
  23. data/lib/active_record/base.rb +2 -3
  24. data/lib/active_record/coders/json.rb +14 -5
  25. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +1 -3
  26. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +15 -0
  27. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +51 -12
  28. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +383 -52
  29. data/lib/active_record/connection_adapters/abstract/database_statements.rb +27 -31
  30. data/lib/active_record/connection_adapters/abstract/query_cache.rb +25 -18
  31. data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -24
  32. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +7 -2
  33. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +26 -34
  34. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -1
  35. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +88 -25
  36. data/lib/active_record/connection_adapters/abstract/transaction.rb +16 -3
  37. data/lib/active_record/connection_adapters/abstract_adapter.rb +96 -49
  38. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +43 -11
  39. data/lib/active_record/connection_adapters/column.rb +17 -4
  40. data/lib/active_record/connection_adapters/mysql/database_statements.rb +4 -4
  41. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +2 -0
  42. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +42 -5
  43. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +26 -4
  44. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +27 -22
  45. data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -0
  46. data/lib/active_record/connection_adapters/postgresql/column.rb +2 -4
  47. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +18 -23
  48. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +2 -2
  49. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
  50. data/lib/active_record/connection_adapters/postgresql/quoting.rb +21 -10
  51. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +1 -1
  52. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +8 -21
  53. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +65 -30
  54. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +74 -38
  55. data/lib/active_record/connection_adapters/postgresql_adapter.rb +10 -12
  56. data/lib/active_record/connection_adapters/schema_cache.rb +2 -2
  57. data/lib/active_record/connection_adapters/sqlite3/column.rb +2 -8
  58. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +37 -25
  59. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +0 -8
  60. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -15
  61. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +4 -13
  62. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +57 -33
  63. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +4 -3
  64. data/lib/active_record/connection_adapters/trilogy_adapter.rb +1 -1
  65. data/lib/active_record/connection_adapters.rb +1 -0
  66. data/lib/active_record/connection_handling.rb +8 -12
  67. data/lib/active_record/core.rb +5 -4
  68. data/lib/active_record/counter_cache.rb +33 -8
  69. data/lib/active_record/database_configurations/database_config.rb +5 -1
  70. data/lib/active_record/database_configurations/hash_config.rb +50 -9
  71. data/lib/active_record/database_configurations/url_config.rb +13 -3
  72. data/lib/active_record/database_configurations.rb +7 -3
  73. data/lib/active_record/delegated_type.rb +1 -1
  74. data/lib/active_record/dynamic_matchers.rb +54 -69
  75. data/lib/active_record/encryption/encryptable_record.rb +4 -4
  76. data/lib/active_record/encryption/encrypted_attribute_type.rb +1 -1
  77. data/lib/active_record/encryption/scheme.rb +1 -1
  78. data/lib/active_record/enum.rb +24 -8
  79. data/lib/active_record/errors.rb +23 -7
  80. data/lib/active_record/explain_registry.rb +0 -1
  81. data/lib/active_record/filter_attribute_handler.rb +73 -0
  82. data/lib/active_record/fixtures.rb +2 -2
  83. data/lib/active_record/future_result.rb +0 -2
  84. data/lib/active_record/gem_version.rb +3 -3
  85. data/lib/active_record/inheritance.rb +1 -1
  86. data/lib/active_record/insert_all.rb +14 -9
  87. data/lib/active_record/locking/optimistic.rb +7 -0
  88. data/lib/active_record/locking/pessimistic.rb +5 -0
  89. data/lib/active_record/log_subscriber.rb +1 -5
  90. data/lib/active_record/middleware/shard_selector.rb +34 -17
  91. data/lib/active_record/migration/command_recorder.rb +15 -2
  92. data/lib/active_record/migration/compatibility.rb +34 -24
  93. data/lib/active_record/migration/default_schema_versions_formatter.rb +30 -0
  94. data/lib/active_record/migration.rb +26 -16
  95. data/lib/active_record/model_schema.rb +10 -7
  96. data/lib/active_record/nested_attributes.rb +2 -0
  97. data/lib/active_record/persistence.rb +34 -3
  98. data/lib/active_record/query_cache.rb +22 -15
  99. data/lib/active_record/query_logs.rb +3 -7
  100. data/lib/active_record/railtie.rb +32 -3
  101. data/lib/active_record/railties/databases.rake +16 -4
  102. data/lib/active_record/railties/job_checkpoints.rb +15 -0
  103. data/lib/active_record/railties/job_runtime.rb +10 -11
  104. data/lib/active_record/reflection.rb +42 -3
  105. data/lib/active_record/relation/batches.rb +26 -12
  106. data/lib/active_record/relation/calculations.rb +20 -9
  107. data/lib/active_record/relation/delegation.rb +0 -1
  108. data/lib/active_record/relation/finder_methods.rb +28 -12
  109. data/lib/active_record/relation/merger.rb +2 -2
  110. data/lib/active_record/relation/predicate_builder/array_handler.rb +1 -3
  111. data/lib/active_record/relation/predicate_builder.rb +2 -2
  112. data/lib/active_record/relation/query_attribute.rb +3 -1
  113. data/lib/active_record/relation/query_methods.rb +40 -31
  114. data/lib/active_record/relation/where_clause.rb +2 -11
  115. data/lib/active_record/relation.rb +26 -14
  116. data/lib/active_record/result.rb +44 -21
  117. data/lib/active_record/sanitization.rb +2 -0
  118. data/lib/active_record/schema_dumper.rb +12 -10
  119. data/lib/active_record/scoping.rb +0 -1
  120. data/lib/active_record/signed_id.rb +43 -15
  121. data/lib/active_record/statement_cache.rb +13 -9
  122. data/lib/active_record/store.rb +44 -19
  123. data/lib/active_record/tasks/abstract_tasks.rb +76 -0
  124. data/lib/active_record/tasks/database_tasks.rb +2 -21
  125. data/lib/active_record/tasks/mysql_database_tasks.rb +3 -40
  126. data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -39
  127. data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -26
  128. data/lib/active_record/test_databases.rb +10 -2
  129. data/lib/active_record/test_fixtures.rb +27 -2
  130. data/lib/active_record/testing/query_assertions.rb +8 -2
  131. data/lib/active_record/timestamp.rb +4 -2
  132. data/lib/active_record/transaction.rb +2 -5
  133. data/lib/active_record/transactions.rb +32 -10
  134. data/lib/active_record/type/hash_lookup_type_map.rb +2 -1
  135. data/lib/active_record/type/internal/timezone.rb +7 -0
  136. data/lib/active_record/type/json.rb +15 -2
  137. data/lib/active_record/type/serialized.rb +11 -9
  138. data/lib/active_record/type/type_map.rb +1 -1
  139. data/lib/active_record/type_caster/connection.rb +2 -1
  140. data/lib/active_record/validations/associated.rb +1 -1
  141. data/lib/active_record.rb +65 -3
  142. data/lib/arel/alias_predication.rb +2 -0
  143. data/lib/arel/crud.rb +6 -11
  144. data/lib/arel/nodes/count.rb +2 -2
  145. data/lib/arel/nodes/function.rb +4 -10
  146. data/lib/arel/nodes/named_function.rb +2 -2
  147. data/lib/arel/nodes/node.rb +1 -1
  148. data/lib/arel/nodes.rb +0 -2
  149. data/lib/arel/predications.rb +3 -1
  150. data/lib/arel/select_manager.rb +7 -2
  151. data/lib/arel/visitors/dot.rb +0 -3
  152. data/lib/arel/visitors/postgresql.rb +55 -0
  153. data/lib/arel/visitors/sqlite.rb +55 -8
  154. data/lib/arel/visitors/to_sql.rb +3 -21
  155. data/lib/arel.rb +3 -1
  156. metadata +14 -10
  157. data/lib/active_record/normalization.rb +0 -163
data/CHANGELOG.md CHANGED
@@ -1,194 +1,79 @@
1
- ## Rails 8.0.5.1 (July 29, 2026) ##
1
+ ## Rails 8.1.0.beta1 (September 04, 2025) ##
2
2
 
3
- * No changes.
3
+ * Remove deprecated `:unsigned_float` and `:unsigned_decimal` column methods for MySQL.
4
4
 
5
+ *Rafael Mendonça França*
5
6
 
6
- ## Rails 8.0.5 (March 24, 2026) ##
7
-
8
- * Fix `insert_all` and `upsert_all` log message when called on anonymous classes.
9
-
10
- *Gabriel Sobrinho*
11
-
12
- * Respect `ActiveRecord::SchemaDumper.ignore_tables` when dumping SQLite virtual tables.
13
-
14
- *Hans Schnedlitz*
15
-
16
- * Restore previous instrumenter after `execute_or_skip`
17
-
18
- `FutureResult#execute_or_skip` replaces the thread's instrumenter with an
19
- `EventBuffer` to collect events published during async query execution.
20
- If the global async executor is saturated and the `caller_runs` fallback
21
- executes the task on the calling thread, we need to make sure the previous
22
- instrumenter is restored or the stale `EventBuffer` would stay in place and
23
- permanently swallow all subsequent `sql.active_record` notifications on
24
- that thread.
25
-
26
- *Rosa Gutierrez*
27
-
28
- * Fix Ruby 4.0 delegator warning when calling inspect on ActiveRecord::Type::Serialized.
29
-
30
- *Hammad Khan*
31
-
32
- * Fix support for table names containing hyphens.
33
-
34
- *Evgeniy Demin*
35
-
36
- * Fix column deduplication for SQLite3 and PostgreSQL virtual (generated) columns.
37
-
38
- `Column#==` and `Column#hash` now account for `virtual?` so that the
39
- `Deduplicable` registry does not treat a generated column and a regular
40
- column with the same name and type as identical. Previously, if a
41
- generated column was registered first, a regular column on a different
42
- table could be deduplicated to the generated instance, silently
43
- excluding it from INSERT/UPDATE statements.
44
-
45
- *Jay Huber*
46
-
47
- * Fix merging relations with arel equality predicates with null relations.
48
-
49
- *fatkodima*
50
-
51
- * Fix SQLite3 schema dump for non-autoincrement integer primary keys.
52
-
53
- Previously, `schema.rb` should incorrectly restore that table with an auto incrementing
54
- primary key.
55
-
56
- *Chris Hasiński*
57
-
58
- * Fix PostgreSQL `schema_search_path` not being reapplied after `reset!` or `reconnect!`.
59
-
60
- The `schema_search_path` configured in `database.yml` is now correctly
61
- reapplied instead of falling back to PostgreSQL defaults.
62
-
63
- *Tobias Egli*
64
-
65
- * Ensure batched preloaded associations accounts for klass when grouping to avoid issues with STI.
66
-
67
- *zzak*, *Stjepan Hadjic*
68
-
69
- * Fix `ActiveRecord::SoleRecordExceeded#record` to return the relation.
70
-
71
- This was the case until Rails 7.2, but starting from 8.0 it
72
- started mistakenly returning the model class.
73
-
74
- *Jean Boussier*
75
-
76
- * Improve PostgreSQLAdapter resilience to Timeout.timeout.
77
-
78
- Better handle asynchronous exceptions being thrown inside
79
- the `reconnect!` method.
80
-
81
- This may fixes some deep errors such as:
82
-
83
- ```
84
- undefined method `key?' for nil:NilClass (NoMethodError)
85
- if !type_map.key?(oid)
86
- ```
87
-
88
- *Jean Boussier*
89
-
90
- * Fix `eager_load` when loading `has_many` assocations with composite primary keys.
91
-
92
- This would result in some records being loaded multiple times.
93
-
94
- *Martin-Alexander*
95
-
96
-
97
- ## Rails 8.0.4.1 (March 23, 2026) ##
98
-
99
- * No changes.
100
-
101
-
102
- ## Rails 8.0.4 (October 28, 2025) ##
103
-
104
- * Fix SQLite3 data loss during table alterations with CASCADE foreign keys.
105
-
106
- When altering a table in SQLite3 that is referenced by child tables with
107
- `ON DELETE CASCADE` foreign keys, ActiveRecord would silently delete all
108
- data from the child tables. This occurred because SQLite requires table
109
- recreation for schema changes, and during this process the original table
110
- is temporarily dropped, triggering CASCADE deletes on child tables.
111
-
112
- The root cause was incorrect ordering of operations. The original code
113
- wrapped `disable_referential_integrity` inside a transaction, but
114
- `PRAGMA foreign_keys` cannot be modified inside a transaction in SQLite -
115
- attempting to do so simply has no effect. This meant foreign keys remained
116
- enabled during table recreation, causing CASCADE deletes to fire.
117
-
118
- The fix reverses the order to follow the official SQLite 12-step ALTER TABLE
119
- procedure: `disable_referential_integrity` now wraps the transaction instead
120
- of being wrapped by it. This ensures foreign keys are properly disabled
121
- before the transaction starts and re-enabled after it commits, preventing
122
- CASCADE deletes while maintaining data integrity through atomic transactions.
123
-
124
- *Ruy Rocha*
125
-
126
- * Add support for bound SQL literals in CTEs.
127
-
128
- *Nicolas Bachschmidt*
129
-
130
- * Fix `belongs_to` associations not to clear the entire composite primary key.
131
-
132
- When clearing a `belongs_to` association that references a model with composite primary key,
133
- only the optional part of the key should be cleared.
134
-
135
- *zzak*
136
-
137
- * Fix invalid records being autosaved when distantly associated records are marked for deletion.
7
+ * Remove deprecated `:retries` option for the SQLite3 adapter.
138
8
 
139
- *Ian Terrell*, *axlekb AB*
9
+ *Rafael Mendonça França*
140
10
 
11
+ * Introduce new database configuration options `keepalive`, `max_age`, and
12
+ `min_connections` -- and rename `pool` to `max_connections` to match.
141
13
 
142
- ## Rails 8.0.3 (September 22, 2025) ##
14
+ There are no changes to default behavior, but these allow for more specific
15
+ control over pool behavior.
143
16
 
144
- * Fix query cache for pinned connections in multi threaded transactional tests
17
+ *Matthew Draper*, *Chris AtLee*, *Rachael Wright-Munn*
145
18
 
146
- When a pinned connection is used across separate threads, they now use a separate cache store
147
- for each thread.
19
+ * Move `LIMIT` validation from query generation to when `limit()` is called.
148
20
 
149
- This improve accuracy of system tests, and any test using multiple threads.
21
+ *Hartley McGuire*, *Shuyang*
150
22
 
151
- *Heinrich Lee Yu*, *Jean Boussier*
23
+ * Add `ActiveRecord::CheckViolation` error class for check constraint violations.
152
24
 
153
- * Don't add `id_value` attribute alias when attribute/column with that name already exists.
25
+ *Ryuta Kamizono*
154
26
 
155
- *Rob Lewis*
27
+ * Add `ActiveRecord::ExclusionViolation` error class for exclusion constraint violations.
156
28
 
157
- * Fix false positive change detection involving STI and polymorphic has one relationships.
29
+ When an exclusion constraint is violated in PostgreSQL, the error will now be raised
30
+ as `ActiveRecord::ExclusionViolation` instead of the generic `ActiveRecord::StatementInvalid`,
31
+ making it easier to handle these specific constraint violations in application code.
158
32
 
159
- Polymorphic `has_one` relationships would always be considered changed when defined in a STI child
160
- class, causing nedless extra autosaves.
33
+ This follows the same pattern as other constraint violation error classes like
34
+ `RecordNotUnique` for unique constraint violations and `InvalidForeignKey` for
35
+ foreign key constraint violations.
161
36
 
162
- *David Fritsch*
37
+ *Ryuta Kamizono*
163
38
 
164
- * Skip calling `PG::Connection#cancel` in `cancel_any_running_query`
165
- when using libpq >= 18 with pg < 1.6.0, due to incompatibility.
166
- Rollback still runs, but may take longer.
39
+ * Attributes filtered by `filter_attributes` will now also be filtered by `filter_parameters`
40
+ so sensitive information is not leaked.
167
41
 
168
- *Yasuo Honda*, *Lars Kanis*
42
+ *Jill Klang*
169
43
 
170
- * Fix stale association detection for polymorphic `belongs_to`.
44
+ * Add `connection.current_transaction.isolation` API to check current transaction's isolation level.
171
45
 
172
- *Florent Beaurain*, *Thomas Crambert*
46
+ Returns the isolation level if it was explicitly set via the `isolation:` parameter
47
+ or through `ActiveRecord.with_transaction_isolation_level`, otherwise returns `nil`.
48
+ Nested transactions return the parent transaction's isolation level.
173
49
 
174
- * Fix removal of PostgreSQL version comments in `structure.sql` for latest PostgreSQL versions which include `\restrict`
50
+ ```ruby
51
+ # Returns nil when no transaction
52
+ User.connection.current_transaction.isolation # => nil
175
53
 
176
- *Brendan Weibrecht*
54
+ # Returns explicitly set isolation level
55
+ User.transaction(isolation: :serializable) do
56
+ User.connection.current_transaction.isolation # => :serializable
57
+ end
177
58
 
178
- * Allow setting `schema_format` in database configuration.
59
+ # Returns nil when isolation not explicitly set
60
+ User.transaction do
61
+ User.connection.current_transaction.isolation # => nil
62
+ end
179
63
 
64
+ # Nested transactions inherit parent's isolation
65
+ User.transaction(isolation: :read_committed) do
66
+ User.transaction do
67
+ User.connection.current_transaction.isolation # => :read_committed
68
+ end
69
+ end
180
70
  ```
181
- primary:
182
- schema_format: ruby
183
- ```
184
-
185
- Useful in multi-database setups to have different formats per-database.
186
71
 
187
- *T S Vallender*
72
+ *Kir Shatrov*
188
73
 
189
- * Use ntuples to populate row_count instead of count for Postgres
74
+ * Emit a warning for pg gem < 1.6.0 when using PostgreSQL 18+
190
75
 
191
- *Jonathan Calvert*
76
+ *Yasuo Honda*
192
77
 
193
78
  * Fix `#merge` with `#or` or `#and` and a mixture of attributes and SQL strings resulting in an incorrect query.
194
79
 
@@ -228,722 +113,601 @@
228
113
 
229
114
  *Joshua Young*
230
115
 
231
- * Fix inline `has_and_belongs_to_many` fixtures for tables with composite primary keys.
232
-
233
- *fatkodima*
234
-
235
- * Fix migration log message for down operations.
236
-
237
- *Bernardo Barreto*
238
-
239
- * Prepend `extra_flags` in postgres' `structure_load`
240
-
241
- When specifying `structure_load_flags` with a postgres adapter, the flags
242
- were appended to the default flags, instead of prepended.
243
- This caused issues with flags not being taken into account by postgres.
244
-
245
- *Alice Loeser*
246
-
247
- * Fix `annotate` comments to propagate to `update_all`/`delete_all`.
116
+ * Make schema dumper to account for `ActiveRecord.dump_schemas` when dumping in `:ruby` format.
248
117
 
249
118
  *fatkodima*
250
119
 
251
- * Fix checking whether an unpersisted record is `include?`d in a strictly
252
- loaded `has_and_belongs_to_many` association.
253
-
254
- *Hartley McGuire*
255
-
256
- * `create_or_find_by` will now correctly rollback a transaction.
257
-
258
- When using `create_or_find_by`, raising a ActiveRecord::Rollback error
259
- in a `after_save` callback had no effect, the transaction was committed
260
- and a record created.
261
-
262
- *Edouard Chin*
263
-
264
- * Gracefully handle `Timeout.timeout` firing during connection configuration.
265
-
266
- Use of `Timeout.timeout` could result in improperly initialized database connection.
267
-
268
- This could lead to a partially configured connection being used, resulting in various exceptions,
269
- the most common being with the PostgreSQLAdapter raising `undefined method 'key?' for nil`
270
- or `TypeError: wrong argument type nil (expected PG::TypeMap)`.
271
-
272
- *Jean Boussier*
273
-
274
- * Fix stale state for composite foreign keys in belongs_to associations.
275
-
276
- *Varun Sharma*
277
-
120
+ * Add `:touch` option to `update_column`/`update_columns` methods.
278
121
 
279
- ## Rails 8.0.2.1 (August 13, 2025) ##
280
-
281
- * Call inspect on ids in RecordNotFound error
282
-
283
- [CVE-2025-55193]
122
+ ```ruby
123
+ # Will update :updated_at/:updated_on alongside :nice column.
124
+ user.update_column(:nice, true, touch: true)
284
125
 
285
- *Gannon McGibbon*, *John Hawthorn*
126
+ # Will update :updated_at/:updated_on alongside :last_ip column
127
+ user.update_columns(last_ip: request.remote_ip, touch: true)
128
+ ```
286
129
 
130
+ *Dmitrii Ivliev*
287
131
 
288
- ## Rails 8.0.2 (March 12, 2025) ##
132
+ * Optimize Active Record batching further when using ranges.
289
133
 
290
- * Fix inverting `rename_enum_value` when `:from`/`:to` are provided.
134
+ Tested on a PostgreSQL table with 10M records and batches of 10k records, the generation
135
+ of relations for the 1000 batches was `4.8x` faster (`6.8s` vs. `1.4s`), used `900x`
136
+ less bandwidth (`180MB` vs. `0.2MB`) and allocated `45x` less memory (`490MB` vs. `11MB`).
291
137
 
292
- *fatkodima*
138
+ *Maxime Réty*, *fatkodima*
293
139
 
294
- * Prevent persisting invalid record.
140
+ * Include current character length in error messages for index and table name length validations.
295
141
 
296
- *Edouard Chin*
297
-
298
- * Fix inverting `drop_table` without options.
299
-
300
- *fatkodima*
142
+ *Joshua Young*
301
143
 
302
- * Fix count with group by qualified name on loaded relation.
144
+ * Add `rename_schema` method for PostgreSQL.
303
145
 
304
- *Ryuta Kamizono*
305
-
306
- * Fix `sum` with qualified name on loaded relation.
146
+ *T S Vallender*
307
147
 
308
- *Chris Gunther*
148
+ * Implement support for deprecating associations:
309
149
 
310
- * The SQLite3 adapter quotes non-finite Numeric values like "Infinity" and "NaN".
150
+ ```ruby
151
+ has_many :posts, deprecated: true
152
+ ```
311
153
 
312
- *Mike Dalessio*
154
+ With that, Active Record will report any usage of the `posts` association.
313
155
 
314
- * Handle libpq returning a database version of 0 on no/bad connection in `PostgreSQLAdapter`.
156
+ Three reporting modes are supported (`:warn`, `:raise`, and `:notify`), and
157
+ backtraces can be enabled or disabled. Defaults are `:warn` mode and
158
+ disabled backtraces.
315
159
 
316
- Before, this version would be cached and an error would be raised during connection configuration when
317
- comparing it with the minimum required version for the adapter. This meant that the connection could
318
- never be successfully configured on subsequent reconnection attempts.
160
+ Please, check the docs for further details.
319
161
 
320
- Now, this is treated as a connection failure consistent with libpq, raising a `ActiveRecord::ConnectionFailed`
321
- and ensuring the version isn't cached, which allows the version to be retrieved on the next connection attempt.
162
+ *Xavier Noria*
322
163
 
323
- *Joshua Young*, *Rian McGuire*
164
+ * PostgreSQL adapter create DB now supports `locale_provider` and `locale`.
324
165
 
325
- * Fix error handling during connection configuration.
166
+ *Bengt-Ove Hollaender*
326
167
 
327
- Active Record wasn't properly handling errors during the connection configuration phase.
328
- This could lead to a partially configured connection being used, resulting in various exceptions,
329
- the most common being with the PostgreSQLAdapter raising `undefined method `key?' for nil`
330
- or `TypeError: wrong argument type nil (expected PG::TypeMap)`.
168
+ * Use ntuples to populate row_count instead of count for Postgres
331
169
 
332
- *Jean Boussier*
170
+ *Jonathan Calvert*
333
171
 
334
- * Fix a case where a non-retryable query could be marked retryable.
172
+ * Fix checking whether an unpersisted record is `include?`d in a strictly
173
+ loaded `has_and_belongs_to_many` association.
335
174
 
336
175
  *Hartley McGuire*
337
176
 
338
- * Handle circular references when autosaving associations.
177
+ * Add ability to change transaction isolation for all pools within a block.
339
178
 
340
- *zzak*
341
-
342
- * PoolConfig no longer keeps a reference to the connection class.
179
+ This functionality is useful if your application needs to change the database
180
+ transaction isolation for a request or action.
343
181
 
344
- Keeping a reference to the class caused subtle issues when combined with reloading in
345
- development. Fixes #54343.
182
+ Calling `ActiveRecord.with_transaction_isolation_level(level) {}` in an around filter or
183
+ middleware will set the transaction isolation for all pools accessed within the block,
184
+ but not for the pools that aren't.
346
185
 
347
- *Mike Dalessio*
348
-
349
- * Fix SQL notifications sometimes not sent when using async queries.
186
+ This works with explicit and implicit transactions:
350
187
 
351
188
  ```ruby
352
- Post.async_count
353
- ActiveSupport::Notifications.subscribed(->(*) { "Will never reach here" }) do
354
- Post.count
189
+ ActiveRecord.with_transaction_isolation_level(:read_committed) do
190
+ Tag.transaction do # opens a transaction explicitly
191
+ Tag.create!
192
+ end
355
193
  end
356
194
  ```
357
195
 
358
- In rare circumstances and under the right race condition, Active Support notifications
359
- would no longer be dispatched after using an asynchronous query.
360
- This is now fixed.
361
-
362
- *Edouard Chin*
363
-
364
- * Fix support for PostgreSQL enum types with commas in their name.
365
-
366
- *Arthur Hess*
367
-
368
- * Fix inserts on MySQL with no RETURNING support for a table with multiple auto populated columns.
369
-
370
- *Nikita Vasilevsky*
371
-
372
- * Fix joining on a scoped association with string joins and bind parameters.
373
-
374
196
  ```ruby
375
- class Instructor < ActiveRecord::Base
376
- has_many :instructor_roles, -> { active }
197
+ ActiveRecord.with_transaction_isolation_level(:read_committed) do
198
+ Tag.create! # opens a transaction implicitly
377
199
  end
378
-
379
- class InstructorRole < ActiveRecord::Base
380
- scope :active, -> {
381
- joins("JOIN students ON instructor_roles.student_id = students.id")
382
- .where(students { status: 1 })
383
- }
384
- end
385
-
386
- Instructor.joins(:instructor_roles).first
387
200
  ```
388
201
 
389
- The above example would result in `ActiveRecord::StatementInvalid` because the
390
- `active` scope bind parameters would be lost.
391
-
392
- *Jean Boussier*
393
-
394
- * Fix a potential race condition with system tests and transactional fixtures.
395
-
396
- *Sjoerd Lagarde*
202
+ *Eileen M. Uchitelle*
397
203
 
398
- * Fix autosave associations to no longer validated unmodified associated records.
204
+ * Raise `ActiveRecord::MissingRequiredOrderError` when order dependent finder methods (e.g. `#first`, `#last`) are
205
+ called without `order` values on the relation, and the model does not have any order columns (`implicit_order_column`,
206
+ `query_constraints`, or `primary_key`) to fall back on.
399
207
 
400
- Active Record was incorrectly performing validation on associated record that
401
- weren't created nor modified as part of the transaction:
208
+ This change will be introduced with a new framework default for Rails 8.1, and the current behavior of not raising
209
+ an error has been deprecated with the aim of removing the configuration option in Rails 8.2.
402
210
 
403
211
  ```ruby
404
- Post.create!(author: User.find(1)) # Fail if user is invalid
212
+ config.active_record.raise_on_missing_required_finder_order_columns = true
405
213
  ```
406
214
 
407
- *Jean Boussier*
408
-
409
- * Remember when a database connection has recently been verified (for
410
- two seconds, by default), to avoid repeated reverifications during a
411
- single request.
412
-
413
- This should recreate a similar rate of verification as in Rails 7.1,
414
- where connections are leased for the duration of a request, and thus
415
- only verified once.
416
-
417
- *Matthew Draper*
418
-
419
-
420
- ## Rails 8.0.1 (December 13, 2024) ##
421
-
422
- * Fix removing foreign keys with :restrict action for MySQL.
423
-
424
- *fatkodima*
425
-
426
- * Fix a race condition in `ActiveRecord::Base#method_missing` when lazily defining attributes.
427
-
428
- If multiple thread were concurrently triggering attribute definition on the same model,
429
- it could result in a `NoMethodError` being raised.
430
-
431
- *Jean Boussier*
432
-
433
- * Fix MySQL default functions getting dropped when changing a column's nullability.
434
-
435
- *Bastian Bartmann*
436
-
437
- * Fix `add_unique_constraint`/`add_check_constraint`/`add_foreign_key` to be revertible when given invalid options.
438
-
439
- *fatkodima*
440
-
441
- * Fix asynchronous destroying of polymorphic `belongs_to` associations.
442
-
443
- *fatkodima*
444
-
445
- * Fix `insert_all` to not update existing records.
446
-
447
- *fatkodima*
448
-
449
- * `NOT VALID` constraints should not dump in `create_table`.
450
-
451
- *Ryuta Kamizono*
452
-
453
- * Fix finding by nil composite primary key association.
454
-
455
- *fatkodima*
456
-
457
- * Properly reset composite primary key configuration when setting a primary key.
458
-
459
- *fatkodima*
460
-
461
- * Fix Mysql2Adapter support for prepared statements
462
-
463
- Using prepared statements with MySQL could result in a `NoMethodError` exception.
464
-
465
- *Jean Boussier*, *Leo Arnold*, *zzak*
466
-
467
- * Fix parsing of SQLite foreign key names when they contain non-ASCII characters
468
-
469
- *Zacharias Knudsen*
470
-
471
- * Fix parsing of MySQL 8.0.16+ CHECK constraints when they contain new lines.
472
-
473
- *Steve Hill*
474
-
475
- * Ensure normalized attribute queries use `IS NULL` consistently for `nil` and normalized `nil` values.
476
-
477
215
  *Joshua Young*
478
216
 
479
- * Fix `sum` when performing a grouped calculation.
217
+ * `:class_name` is now invalid in polymorphic `belongs_to` associations.
480
218
 
481
- `User.group(:friendly).sum` no longer worked. This is fixed.
219
+ Reason is `:class_name` does not make sense in those associations because
220
+ the class name of target records is dynamic and stored in the type column.
482
221
 
483
- *Edouard Chin*
222
+ Existing polymorphic associations setting this option can just delete it.
223
+ While it did not raise, it had no effect anyway.
484
224
 
485
- * Restore back the ability to pass only database name to `DATABASE_URL`.
225
+ *Xavier Noria*
486
226
 
487
- *fatkodima*
227
+ * Add support for multiple databases to `db:migrate:reset`.
488
228
 
229
+ *Joé Dupuis*
489
230
 
490
- ## Rails 8.0.0.1 (December 10, 2024) ##
231
+ * Add `affected_rows` to `ActiveRecord::Result`.
491
232
 
492
- * No changes.
233
+ *Jenny Shen*
493
234
 
235
+ * Enable passing retryable SqlLiterals to `#where`.
494
236
 
495
- ## Rails 8.0.0 (November 07, 2024) ##
237
+ *Hartley McGuire*
496
238
 
497
- * Fix support for `query_cache: false` in `database.yml`.
239
+ * Set default for primary keys in `insert_all`/`upsert_all`.
498
240
 
499
- `query_cache: false` would no longer entirely disable the Active Record query cache.
241
+ Previously in Postgres, updating and inserting new records in one upsert wasn't possible
242
+ due to null primary key values. `nil` primary key values passed into `insert_all`/`upsert_all`
243
+ are now implicitly set to the default insert value specified by adapter.
500
244
 
501
- *zzak*
245
+ *Jenny Shen*
502
246
 
247
+ * Add a load hook `active_record_database_configurations` for `ActiveRecord::DatabaseConfigurations`
503
248
 
504
- ## Rails 8.0.0.rc2 (October 30, 2024) ##
249
+ *Mike Dalessio*
505
250
 
506
- * NULLS NOT DISTINCT works with UNIQUE CONSTRAINT as well as UNIQUE INDEX.
251
+ * Use `TRUE` and `FALSE` for SQLite queries with boolean columns.
507
252
 
508
- *Ryuta Kamizono*
253
+ *Hartley McGuire*
509
254
 
510
- * The `db:prepare` task no longer loads seeds when a non-primary database is created.
255
+ * Bump minimum supported SQLite to 3.23.0.
511
256
 
512
- Previously, the `db:prepare` task would load seeds whenever a new database
513
- is created, leading to potential loss of data if a database is added to an
514
- existing environment.
257
+ *Hartley McGuire*
515
258
 
516
- Introduces a new database config property `seeds` to control whether seeds
517
- are loaded during `db:prepare` which defaults to `true` for primary database
518
- configs and `false` otherwise.
259
+ * Allow allocated Active Records to lookup associations.
519
260
 
520
- Fixes #53348.
261
+ Previously, the association cache isn't setup on allocated record objects, so association
262
+ lookups will crash. Test frameworks like mocha use allocate to check for stubbable instance
263
+ methods, which can trigger an association lookup.
521
264
 
522
- *Mike Dalessio*
265
+ *Gannon McGibbon*
523
266
 
524
- * `PG::UnableToSend: no connection to the server` is now retryable as a connection-related exception
267
+ * Encryption now supports `support_unencrypted_data: true` being set per-attribute.
525
268
 
526
- *Kazuma Watanabe*
269
+ Previously this only worked if `ActiveRecord::Encryption.config.support_unencrypted_data == true`.
270
+ Now, if the global config is turned off, you can still opt in for a specific attribute.
527
271
 
528
- * Fix strict loading propagation even if statement cache is not used.
272
+ ```ruby
273
+ # ActiveRecord::Encryption.config.support_unencrypted_data = true
274
+ class User < ActiveRecord::Base
275
+ encrypts :name, support_unencrypted_data: false # only supports encrypted data
276
+ encrypts :email # supports encrypted or unencrypted data
277
+ end
278
+ ```
529
279
 
530
- *Ryuta Kamizono*
280
+ ```ruby
281
+ # ActiveRecord::Encryption.config.support_unencrypted_data = false
282
+ class User < ActiveRecord::Base
283
+ encrypts :name, support_unencrypted_data: true # supports encrypted or unencrypted data
284
+ encrypts :email # only supports encrypted data
285
+ end
286
+ ```
531
287
 
532
- * Allow `rename_enum` accepts two from/to name arguments as `rename_table` does so.
288
+ *Alex Ghiculescu*
533
289
 
534
- *Ryuta Kamizono*
290
+ * Model generator no longer needs a database connection to validate column types.
535
291
 
292
+ *Mike Dalessio*
536
293
 
537
- ## Rails 8.0.0.rc1 (October 19, 2024) ##
294
+ * Allow signed ID verifiers to be configurable via `Rails.application.message_verifiers`
538
295
 
539
- * Remove deprecated support to setting `ENV["SCHEMA_CACHE"]`.
296
+ Prior to this change, the primary way to configure signed ID verifiers was
297
+ to set `signed_id_verifier` on each model class:
540
298
 
541
- *Rafael Mendonça França*
299
+ ```ruby
300
+ Post.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
301
+ Comment.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
302
+ ```
542
303
 
543
- * Remove deprecated support to passing a database name to `cache_dump_filename`.
304
+ And if the developer did not set `signed_id_verifier`, a verifier would be
305
+ instantiated with a secret derived from `secret_key_base` and the following
306
+ options:
544
307
 
545
- *Rafael Mendonça França*
308
+ ```ruby
309
+ { digest: "SHA256", serializer: JSON, url_safe: true }
310
+ ```
546
311
 
547
- * Remove deprecated `ActiveRecord::ConnectionAdapters::ConnectionPool#connection`.
312
+ Thus it was cumbersome to rotate configuration for all verifiers.
548
313
 
549
- *Rafael Mendonça França*
314
+ This change defines a new Rails config: [`config.active_record.use_legacy_signed_id_verifier`][].
315
+ The default value is `:generate_and_verify`, which preserves the previous
316
+ behavior. However, when set to `:verify`, signed ID verifiers will use
317
+ configuration from `Rails.application.message_verifiers` (specifically,
318
+ `Rails.application.message_verifiers["active_record/signed_id"]`) to
319
+ generate and verify signed IDs, but will also verify signed IDs using the
320
+ older configuration.
550
321
 
551
- * Remove deprecated `config.active_record.sqlite3_deprecated_warning`.
322
+ To avoid complication, the new behavior only applies when `signed_id_verifier_secret`
323
+ is not set on a model class or any of its ancestors. Additionally,
324
+ `signed_id_verifier_secret` is now deprecated. If you are currently setting
325
+ `signed_id_verifier_secret` on a model class, you can set `signed_id_verifier`
326
+ instead:
552
327
 
553
- *Rafael Mendonça França*
328
+ ```ruby
329
+ # BEFORE
330
+ Post.signed_id_verifier_secret = "my secret"
554
331
 
555
- * Remove deprecated `config.active_record.warn_on_records_fetched_greater_than`.
332
+ # AFTER
333
+ Post.signed_id_verifier = ActiveSupport::MessageVerifier.new("my secret", digest: "SHA256", serializer: JSON, url_safe: true)
334
+ ```
556
335
 
557
- *Rafael Mendonça França*
336
+ To ease migration, `signed_id_verifier` has also been changed to behave as a
337
+ `class_attribute` (i.e. inheritable), but _only when `signed_id_verifier_secret`
338
+ is not set_:
558
339
 
559
- * Remove deprecated support for defining `enum` with keyword arguments.
340
+ ```ruby
341
+ # BEFORE
342
+ ActiveRecord::Base.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
343
+ Post.signed_id_verifier == ActiveRecord::Base.signed_id_verifier # => false
560
344
 
561
- *Rafael Mendonça França*
345
+ # AFTER
346
+ ActiveRecord::Base.signed_id_verifier = ActiveSupport::MessageVerifier.new(...)
347
+ Post.signed_id_verifier == ActiveRecord::Base.signed_id_verifier # => true
562
348
 
563
- * Remove deprecated support to finding database adapters that aren't registered to Active Record.
349
+ Post.signed_id_verifier_secret = "my secret" # => deprecation warning
350
+ Post.signed_id_verifier == ActiveRecord::Base.signed_id_verifier # => false
351
+ ```
564
352
 
565
- *Rafael Mendonça França*
353
+ Note, however, that it is recommended to eventually migrate from
354
+ model-specific verifiers to a unified configuration managed by
355
+ `Rails.application.message_verifiers`. `ActiveSupport::MessageVerifier#rotate`
356
+ can facilitate that transition. For example:
566
357
 
567
- * Remove deprecated `config.active_record.allow_deprecated_singular_associations_name`.
358
+ ```ruby
359
+ # BEFORE
360
+ # Generate and verify signed Post IDs using Post-specific configuration
361
+ Post.signed_id_verifier = ActiveSupport::MessageVerifier.new("post secret", ...)
568
362
 
569
- *Rafael Mendonça França*
363
+ # AFTER
364
+ # Generate and verify signed Post IDs using the unified configuration
365
+ Post.signed_id_verifier = Post.signed_id_verifier.dup
366
+ # Fall back to Post-specific configuration when verifying signed IDs
367
+ Post.signed_id_verifier.rotate("post secret", ...)
368
+ ```
570
369
 
571
- * Remove deprecated `config.active_record.commit_transaction_on_non_local_return`.
370
+ [`config.active_record.use_legacy_signed_id_verifier`]: https://guides.rubyonrails.org/v8.1/configuring.html#config-active-record-use-legacy-signed-id-verifier
572
371
 
573
- *Rafael Mendonça França*
372
+ *Ali Sepehri*, *Jonathan Hefner*
574
373
 
575
- * Fix incorrect SQL query when passing an empty hash to `ActiveRecord::Base.insert`.
374
+ * Prepend `extra_flags` in postgres' `structure_load`
576
375
 
577
- *David Stosik*
376
+ When specifying `structure_load_flags` with a postgres adapter, the flags
377
+ were appended to the default flags, instead of prepended.
378
+ This caused issues with flags not being taken into account by postgres.
578
379
 
579
- * Allow to save records with polymorphic join tables that have `inverse_of`
580
- specified.
380
+ *Alice Loeser*
581
381
 
582
- *Markus Doits*
382
+ * Allow bypassing primary key/constraint addition in `implicit_order_column`
583
383
 
584
- * Fix association scopes applying on the incorrect join when using a polymorphic `has_many through:`.
384
+ When specifying multiple columns in an array for `implicit_order_column`, adding
385
+ `nil` as the last element will prevent appending the primary key to order
386
+ conditions. This allows more precise control of indexes used by
387
+ generated queries. It should be noted that this feature does introduce the risk
388
+ of API misbehavior if the specified columns are not fully unique.
585
389
 
586
- *Joshua Young*
390
+ *Issy Long*
587
391
 
588
- * Allow `ActiveRecord::Base#pluck` to accept hash arguments with symbol and string values.
392
+ * Allow setting the `schema_format` via database configuration.
589
393
 
590
- ```ruby
591
- Post.joins(:comments).pluck(:id, comments: :id)
592
- Post.joins(:comments).pluck("id", "comments" => "id")
394
+ ```
395
+ primary:
396
+ schema_format: ruby
593
397
  ```
594
398
 
595
- *Joshua Young*
596
-
597
- * Make Float distinguish between `float4` and `float8` in PostgreSQL.
598
-
599
- Fixes #52742
399
+ Useful for multi-database setups when apps require different formats per-database.
600
400
 
601
- *Ryota Kitazawa*, *Takayuki Nagatomi*
401
+ *T S Vallender*
602
402
 
403
+ * Support disabling indexes for MySQL v8.0.0+ and MariaDB v10.6.0+
603
404
 
604
- ## Rails 8.0.0.beta1 (September 26, 2024) ##
405
+ MySQL 8.0.0 added an option to disable indexes from being used by the query
406
+ optimizer by making them "invisible". This allows the index to still be maintained
407
+ and updated but no queries will be permitted to use it. This can be useful for adding
408
+ new invisible indexes or making existing indexes invisible before dropping them
409
+ to ensure queries are not negatively affected.
410
+ See https://dev.mysql.com/blog-archive/mysql-8-0-invisible-indexes/ for more details.
605
411
 
606
- * Allow `drop_table` to accept an array of table names.
412
+ MariaDB 10.6.0 also added support for this feature by allowing indexes to be "ignored"
413
+ in queries. See https://mariadb.com/kb/en/ignored-indexes/ for more details.
607
414
 
608
- This will let you to drop multiple tables in a single call.
415
+ Active Record now supports this option for MySQL 8.0.0+ and MariaDB 10.6.0+ for
416
+ index creation and alteration where the new index option `enabled: true/false` can be
417
+ passed to column and index methods as below:
609
418
 
610
419
  ```ruby
611
- ActiveRecord::Base.lease_connection.drop_table(:users, :posts)
420
+ add_index :users, :email, enabled: false
421
+ enable_index :users, :email
422
+ add_column :users, :dob, :string, index: { enabled: false }
423
+
424
+ change_table :users do |t|
425
+ t.index :name, enabled: false
426
+ t.index :dob
427
+ t.disable_index :dob
428
+ t.column :username, :string, index: { enabled: false }
429
+ t.references :account, index: { enabled: false }
430
+ end
431
+
432
+ create_table :users do |t|
433
+ t.string :name, index: { enabled: false }
434
+ t.string :email
435
+ t.index :email, enabled: false
436
+ end
612
437
  ```
613
438
 
614
- *Gabriel Sobrinho*
439
+ *Merve Taner*
615
440
 
616
- * Add support for PostgreSQL `IF NOT EXISTS` via the `:if_not_exists` option
617
- on the `add_enum_value` method.
441
+ * Respect `implicit_order_column` in `ActiveRecord::Relation#reverse_order`.
618
442
 
619
- *Ariel Rzezak*
443
+ *Joshua Young*
620
444
 
621
- * When running `db:migrate` on a fresh database, load the databases schemas before running migrations.
445
+ * Add column types to `ActiveRecord::Result` for SQLite3.
622
446
 
623
- *Andrew Novoselac*, *Marek Kasztelnik*
447
+ *Andrew Kane*
624
448
 
625
- * Fix an issue where `.left_outer_joins` used with multiple associations that have
626
- the same child association but different parents does not join all parents.
449
+ * Raise `ActiveRecord::ReadOnlyError` when pessimistically locking with a readonly role.
627
450
 
628
- Previously, using `.left_outer_joins` with the same child association would only join one of the parents.
451
+ *Joshua Young*
629
452
 
630
- Now it will correctly join both parents.
453
+ * Fix using the `SQLite3Adapter`'s `dbconsole` method outside of a Rails application.
631
454
 
632
- Fixes #41498.
455
+ *Hartley McGuire*
633
456
 
634
- *Garrett Blehm*
457
+ * Fix migrating multiple databases with `ActiveRecord::PendingMigration` action.
635
458
 
636
- * Deprecate `unsigned_float` and `unsigned_decimal` short-hand column methods.
459
+ *Gannon McGibbon*
637
460
 
638
- As of MySQL 8.0.17, the UNSIGNED attribute is deprecated for columns of type FLOAT, DOUBLE,
639
- and DECIMAL. Consider using a simple CHECK constraint instead for such columns.
461
+ * Enable automatically retrying idempotent association queries on connection
462
+ errors.
640
463
 
641
- https://dev.mysql.com/doc/refman/8.0/en/numeric-type-syntax.html
464
+ *Hartley McGuire*
642
465
 
643
- *Ryuta Kamizono*
466
+ * Add `allow_retry` to `sql.active_record` instrumentation.
644
467
 
645
- * Drop MySQL 5.5 support.
468
+ This enables identifying queries which queries are automatically retryable on connection errors.
646
469
 
647
- MySQL 5.5 is the only version that does not support datetime with precision,
648
- which we have supported in the core. Now we support MySQL 5.6.4 or later, which
649
- is the first version to support datetime with precision.
470
+ *Hartley McGuire*
650
471
 
651
- *Ryuta Kamizono*
472
+ * Better support UPDATE with JOIN for Postgresql and SQLite3
652
473
 
653
- * Make Active Record asynchronous queries compatible with transactional fixtures.
474
+ Previously when generating update queries with one or more JOIN clauses,
475
+ Active Record would use a sub query which would prevent to reference the joined
476
+ tables in the `SET` clause, for instance:
654
477
 
655
- Previously transactional fixtures would disable asynchronous queries, because transactional
656
- fixtures impose all queries use the same connection.
478
+ ```ruby
479
+ Comment.joins(:post).update_all("title = posts.title")
480
+ ```
657
481
 
658
- Now asynchronous queries will use the connection pinned by transactional fixtures, and behave
659
- much closer to production.
482
+ This is now supported as long as the relation doesn't also use a `LIMIT`, `ORDER` or
483
+ `GROUP BY` clause. This was supported by the MySQL adapter for a long time.
660
484
 
661
485
  *Jean Boussier*
662
486
 
663
- * Deserialize binary data before decrypting
664
-
665
- This ensures that we call `PG::Connection.unescape_bytea` on PostgreSQL before decryption.
666
-
667
- *Donal McBreen*
668
-
669
- * Ensure `ActiveRecord::Encryption.config` is always ready before access.
670
-
671
- Previously, `ActiveRecord::Encryption` configuration was deferred until `ActiveRecord::Base`
672
- was loaded. Therefore, accessing `ActiveRecord::Encryption.config` properties before
673
- `ActiveRecord::Base` was loaded would give incorrect results.
674
-
675
- `ActiveRecord::Encryption` now has its own loading hook so that its configuration is set as
676
- soon as needed.
487
+ * Introduce a before-fork hook in `ActiveSupport::Testing::Parallelization` to clear existing
488
+ connections, to avoid fork-safety issues with the mysql2 adapter.
677
489
 
678
- When `ActiveRecord::Base` is loaded, even lazily, it in turn triggers the loading of
679
- `ActiveRecord::Encryption`, thus preserving the original behavior of having its config ready
680
- before any use of `ActiveRecord::Base`.
490
+ Fixes #41776
681
491
 
682
- *Maxime Réty*
492
+ *Mike Dalessio*, *Donal McBreen*
683
493
 
684
- * Add `TimeZoneConverter#==` method, so objects will be properly compared by
685
- their type, scale, limit & precision.
686
-
687
- Address #52699.
688
-
689
- *Ruy Rocha*
690
-
691
- * Add support for SQLite3 full-text-search and other virtual tables.
692
-
693
- Previously, adding sqlite3 virtual tables messed up `schema.rb`.
494
+ * PoolConfig no longer keeps a reference to the connection class.
694
495
 
695
- Now, virtual tables can safely be added using `create_virtual_table`.
496
+ Keeping a reference to the class caused subtle issues when combined with reloading in
497
+ development. Fixes #54343.
696
498
 
697
- *Zacharias Knudsen*
499
+ *Mike Dalessio*
698
500
 
699
- * Support use of alternative database interfaces via the `database_cli` ActiveRecord configuration option.
501
+ * Fix SQL notifications sometimes not sent when using async queries.
700
502
 
701
503
  ```ruby
702
- Rails.application.configure do
703
- config.active_record.database_cli = { postgresql: "pgcli" }
504
+ Post.async_count
505
+ ActiveSupport::Notifications.subscribed(->(*) { "Will never reach here" }) do
506
+ Post.count
704
507
  end
705
508
  ```
706
509
 
707
- *T S Vallender*
510
+ In rare circumstances and under the right race condition, Active Support notifications
511
+ would no longer be dispatched after using an asynchronous query.
512
+ This is now fixed.
708
513
 
709
- * Add support for dumping table inheritance and native partitioning table definitions for PostgeSQL adapter
514
+ *Edouard Chin*
710
515
 
711
- *Justin Talbott*
516
+ * Eliminate queries loading dumped schema cache on Postgres
712
517
 
713
- * Add support for `ActiveRecord::Point` type casts using `Hash` values
518
+ Improve resiliency by avoiding needing to open a database connection to load the
519
+ type map while defining attribute methods at boot when a schema cache file is
520
+ configured on PostgreSQL databases.
714
521
 
715
- This allows `ActiveRecord::Point` to be cast or serialized from a hash
716
- with `:x` and `:y` keys of numeric values, mirroring the functionality of
717
- existing casts for string and array values. Both string and symbol keys are
718
- supported.
522
+ *James Coleman*
719
523
 
720
- ```ruby
721
- class PostgresqlPoint < ActiveRecord::Base
722
- attribute :x, :point
723
- attribute :y, :point
724
- attribute :z, :point
725
- end
524
+ * `ActiveRecord::Coder::JSON` can be instantiated
726
525
 
727
- val = PostgresqlPoint.new({
728
- x: '(12.34, -43.21)',
729
- y: [12.34, '-43.21'],
730
- z: {x: '12.34', y: -43.21}
731
- })
732
- ActiveRecord::Point.new(12.32, -43.21) == val.x == val.y == val.z
526
+ Options can now be passed to `ActiveRecord::Coder::JSON` when instantiating the coder. This allows:
527
+ ```ruby
528
+ serialize :config, coder: ActiveRecord::Coder::JSON.new(symbolize_names: true)
733
529
  ```
530
+ *matthaigh27*
734
531
 
735
- *Stephen Drew*
532
+ * Deprecate using `insert_all`/`upsert_all` with unpersisted records in associations.
736
533
 
737
- * Replace `SQLite3::Database#busy_timeout` with `#busy_handler_timeout=`.
534
+ Using these methods on associations containing unpersisted records will now
535
+ show a deprecation warning, as the unpersisted records will be lost after
536
+ the operation.
738
537
 
739
- Provides a non-GVL-blocking, fair retry interval busy handler implementation.
538
+ *Nick Schwaderer*
740
539
 
741
- *Stephen Margheim*
540
+ * Make column name optional for `index_exists?`.
742
541
 
743
- * SQLite3Adapter: Translate `SQLite3::BusyException` into `ActiveRecord::StatementTimeout`.
542
+ This aligns well with `remove_index` signature as well, where
543
+ index name doesn't need to be derived from the column names.
744
544
 
745
- *Matthew Nguyen*
545
+ *Ali Ismayiliov*
746
546
 
747
- * Include schema name in `enable_extension` statements in `db/schema.rb`.
547
+ * Change the payload name of `sql.active_record` notification for eager
548
+ loading from "SQL" to "#{model.name} Eager Load".
748
549
 
749
- The schema dumper will now include the schema name in generated
750
- `enable_extension` statements if they differ from the current schema.
550
+ *zzak*
751
551
 
752
- For example, if you have a migration:
552
+ * Enable automatically retrying idempotent `#exists?` queries on connection
553
+ errors.
753
554
 
754
- ```ruby
755
- enable_extension "heroku_ext.pgcrypto"
756
- enable_extension "pg_stat_statements"
757
- ```
555
+ *Hartley McGuire*, *classidied*
758
556
 
759
- then the generated schema dump will also contain:
557
+ * Deprecate usage of unsupported methods in conjunction with `update_all`:
760
558
 
761
- ```ruby
762
- enable_extension "heroku_ext.pgcrypto"
763
- enable_extension "pg_stat_statements"
764
- ```
559
+ `update_all` will now print a deprecation message if a query includes either `WITH`,
560
+ `WITH RECURSIVE` or `DISTINCT` statements. Those were never supported and were ignored
561
+ when generating the SQL query.
765
562
 
766
- *Tony Novak*
563
+ An error will be raised in a future Rails release. This behavior will be consistent
564
+ with `delete_all` which currently raises an error for unsupported statements.
767
565
 
768
- * Fix `ActiveRecord::Encryption::EncryptedAttributeType#type` to return
769
- actual cast type.
566
+ *Edouard Chin*
770
567
 
771
- *Vasiliy Ermolovich*
568
+ * The table columns inside `schema.rb` are now sorted alphabetically.
772
569
 
773
- * SQLite3Adapter: Bulk insert fixtures.
570
+ Previously they'd be sorted by creation order, which can cause merge conflicts when two
571
+ branches modify the same table concurrently.
774
572
 
775
- Previously one insert command was executed for each fixture, now they are
776
- aggregated in a single bulk insert command.
573
+ *John Duff*
777
574
 
778
- *Lázaro Nixon*
575
+ * Introduce versions formatter for the schema dumper.
779
576
 
780
- * PostgreSQLAdapter: Allow `disable_extension` to be called with schema-qualified name.
577
+ It is now possible to override how schema dumper formats versions information inside the
578
+ `structure.sql` file. Currently, the versions are simply sorted in the decreasing order.
579
+ Within large teams, this can potentially cause many merge conflicts near the top of the list.
781
580
 
782
- For parity with `enable_extension`, the `disable_extension` method can be called with a schema-qualified
783
- name (e.g. `disable_extension "myschema.pgcrypto"`). Note that PostgreSQL's `DROP EXTENSION` does not
784
- actually take a schema name (unlike `CREATE EXTENSION`), so the resulting SQL statement will only name
785
- the extension, e.g. `DROP EXTENSION IF EXISTS "pgcrypto"`.
581
+ Now, the custom formatter can be provided with a custom sorting logic (e.g. by hash values
582
+ of the versions), which can greatly reduce the number of conflicts.
786
583
 
787
- *Tony Novak*
584
+ *fatkodima*
788
585
 
789
- * Make `create_schema` / `drop_schema` reversible in migrations.
586
+ * Serialized attributes can now be marked as comparable.
790
587
 
791
- Previously, `create_schema` and `drop_schema` were irreversible migration operations.
588
+ A not rare issue when working with serialized attributes is that the serialized representation of an object
589
+ can change over time. Either because you are migrating from one serializer to the other (e.g. YAML to JSON or to msgpack),
590
+ or because the serializer used subtly changed its output.
792
591
 
793
- *Tony Novak*
592
+ One example is libyaml that used to have some extra trailing whitespaces, and recently fixed that.
593
+ When this sorts of thing happen, you end up with lots of records that report being changed even though
594
+ 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.
794
595
 
795
- * Support batching using custom columns.
596
+ The solution is to instead compare the deserialized representation of the object, however Active Record
597
+ can't assume the deserialized object has a working `==` method. Hence why this new functionality is opt-in.
796
598
 
797
599
  ```ruby
798
- Product.in_batches(cursor: [:shop_id, :id]) do |relation|
799
- # do something with relation
800
- end
600
+ serialize :config, type: Hash, coder: JSON, comparable: true
801
601
  ```
802
602
 
803
- *fatkodima*
804
-
805
- * Use SQLite `IMMEDIATE` transactions when possible.
806
-
807
- Transactions run against the SQLite3 adapter default to IMMEDIATE mode to improve concurrency support and avoid busy exceptions.
808
-
809
- *Stephen Margheim*
810
-
811
- * Raise specific exception when a connection is not defined.
812
-
813
- The new `ConnectionNotDefined` exception provides connection name, shard and role accessors indicating the details of the connection that was requested.
603
+ *Jean Boussier*
814
604
 
815
- *Hana Harencarova*, *Matthew Draper*
605
+ * Fix MySQL default functions getting dropped when changing a column's nullability.
816
606
 
817
- * Delete the deprecated constant `ActiveRecord::ImmutableRelation`.
607
+ *Bastian Bartmann*
818
608
 
819
- *Xavier Noria*
609
+ * SQLite extensions can be configured in `config/database.yml`.
820
610
 
821
- * Fix duplicate callback execution when child autosaves parent with `has_one` and `belongs_to`.
611
+ The database configuration option `extensions:` allows an application to load SQLite extensions
612
+ when using `sqlite3` >= v2.4.0. The array members may be filesystem paths or the names of
613
+ modules that respond to `.to_path`:
822
614
 
823
- Before, persisting a new child record with a new associated parent record would run `before_validation`,
824
- `after_validation`, `before_save` and `after_save` callbacks twice.
615
+ ``` yaml
616
+ development:
617
+ adapter: sqlite3
618
+ extensions:
619
+ - SQLean::UUID # module name responding to `.to_path`
620
+ - .sqlpkg/nalgeon/crypto/crypto.so # or a filesystem path
621
+ - <%= AppExtensions.location %> # or ruby code returning a path
622
+ ```
825
623
 
826
- Now, these callbacks are only executed once as expected.
624
+ *Mike Dalessio*
827
625
 
828
- *Joshua Young*
626
+ * `ActiveRecord::Middleware::ShardSelector` supports granular database connection switching.
829
627
 
830
- * `ActiveRecord::Encryption::Encryptor` now supports a `:compressor` option to customize the compression algorithm used.
628
+ A new configuration option, `class_name:`, is introduced to
629
+ `config.active_record.shard_selector` to allow an application to specify the abstract connection
630
+ class to be switched by the shard selection middleware. The default class is
631
+ `ActiveRecord::Base`.
831
632
 
832
- ```ruby
833
- module ZstdCompressor
834
- def self.deflate(data)
835
- Zstd.compress(data)
836
- end
633
+ For example, this configuration tells `ShardSelector` to switch shards using
634
+ `AnimalsRecord.connected_to`:
837
635
 
838
- def self.inflate(data)
839
- Zstd.decompress(data)
840
- end
841
- end
842
-
843
- class User
844
- encrypts :name, compressor: ZstdCompressor
845
- end
846
636
  ```
847
-
848
- You disable compression by passing `compress: false`.
849
-
850
- ```ruby
851
- class User
852
- encrypts :name, compress: false
853
- end
637
+ config.active_record.shard_selector = { class_name: "AnimalsRecord" }
854
638
  ```
855
639
 
856
- *heka1024*
857
-
858
- * Add condensed `#inspect` for `ConnectionPool`, `AbstractAdapter`, and
859
- `DatabaseConfig`.
860
-
861
- *Hartley McGuire*
862
-
863
- * Add `.shard_keys`, `.sharded?`, & `.connected_to_all_shards` methods.
864
-
865
- ```ruby
866
- class ShardedBase < ActiveRecord::Base
867
- self.abstract_class = true
868
-
869
- connects_to shards: {
870
- shard_one: { writing: :shard_one },
871
- shard_two: { writing: :shard_two }
872
- }
873
- end
640
+ *Mike Dalessio*
874
641
 
875
- class ShardedModel < ShardedBase
876
- end
642
+ * Reset relations after `insert_all`/`upsert_all`.
877
643
 
878
- ShardedModel.shard_keys => [:shard_one, :shard_two]
879
- ShardedModel.sharded? => true
880
- ShardedBase.connected_to_all_shards { ShardedModel.current_shard } => [:shard_one, :shard_two]
881
- ```
644
+ Bulk insert/upsert methods will now call `reset` if used on a relation, matching the behavior of `update_all`.
882
645
 
883
- *Nony Dutton*
646
+ *Milo Winningham*
884
647
 
885
- * Add a `filter` option to `in_order_of` to prioritize certain values in the sorting without filtering the results
886
- by these values.
648
+ * Use `_N` as a parallel tests databases suffixes
887
649
 
888
- *Igor Depolli*
650
+ Peviously, `-N` was used as a suffix. This can cause problems for RDBMSes
651
+ which do not support dashes in database names.
889
652
 
890
- * Fix an issue where the IDs reader method did not return expected results
891
- for preloaded associations in models using composite primary keys.
892
-
893
- *Jay Ang*
653
+ *fatkodima*
894
654
 
895
- * Allow to configure `strict_loading_mode` globally or within a model.
655
+ * Remember when a database connection has recently been verified (for
656
+ two seconds, by default), to avoid repeated reverifications during a
657
+ single request.
896
658
 
897
- Defaults to `:all`, can be changed to `:n_plus_one_only`.
659
+ This should recreate a similar rate of verification as in Rails 7.1,
660
+ where connections are leased for the duration of a request, and thus
661
+ only verified once.
898
662
 
899
- *Garen Torikian*
663
+ *Matthew Draper*
900
664
 
901
- * Add `ActiveRecord::Relation#readonly?`.
665
+ * Allow to reset cache counters for multiple records.
902
666
 
903
- Reflects if the relation has been marked as readonly.
667
+ ```
668
+ Aircraft.reset_counters([1, 2, 3], :wheels_count)
669
+ ```
904
670
 
905
- *Theodor Tonum*
671
+ It produces much fewer queries compared to the custom implementation using looping over ids.
672
+ Previously: `O(ids.size * counters.size)` queries, now: `O(ids.size + counters.size)` queries.
906
673
 
907
- * Improve `ActiveRecord::Store` to raise a descriptive exception if the column is not either
908
- structured (e.g., PostgreSQL +hstore+/+json+, or MySQL +json+) or declared serializable via
909
- `ActiveRecord.store`.
674
+ *fatkodima*
910
675
 
911
- Previously, a `NoMethodError` would be raised when the accessor was read or written:
676
+ * Add `affected_rows` to `sql.active_record` Notification.
912
677
 
913
- NoMethodError: undefined method `accessor' for an instance of ActiveRecord::Type::Text
678
+ *Hartley McGuire*
914
679
 
915
- Now, a descriptive `ConfigurationError` is raised:
680
+ * Fix `sum` when performing a grouped calculation.
916
681
 
917
- ActiveRecord::ConfigurationError: the column 'metadata' has not been configured as a store.
918
- Please make sure the column is declared serializable via 'ActiveRecord.store' or, if your
919
- database supports it, use a structured column type like hstore or json.
682
+ `User.group(:friendly).sum` no longer worked. This is fixed.
920
683
 
921
- *Mike Dalessio*
684
+ *Edouard Chin*
922
685
 
923
- * Fix inference of association model on nested models with the same demodularized name.
686
+ * Add support for enabling or disabling transactional tests per database.
924
687
 
925
- E.g. with the following setup:
688
+ A test class can now override the default `use_transactional_tests` setting
689
+ for individual databases, which can be useful if some databases need their
690
+ current state to be accessible to an external process while tests are running.
926
691
 
927
692
  ```ruby
928
- class Nested::Post < ApplicationRecord
929
- has_one :post, through: :other
693
+ class MostlyTransactionalTest < ActiveSupport::TestCase
694
+ self.use_transactional_tests = true
695
+ skip_transactional_tests_for_database :shared
930
696
  end
931
697
  ```
932
698
 
933
- Before, `#post` would infer the model as `Nested::Post`, but now it correctly infers `Post`.
699
+ *Matthew Cheetham*, *Morgan Mareve*
934
700
 
935
- *Joshua Young*
701
+ * Cast `query_cache` value when using URL configuration.
936
702
 
937
- * Add public method for checking if a table is ignored by the schema cache.
703
+ *zzak*
938
704
 
939
- Previously, an application would need to reimplement `ignored_table?` from the schema cache class to check if a table was set to be ignored. This adds a public method to support this and updates the schema cache to use that directly.
705
+ * NULLS NOT DISTINCT works with UNIQUE CONSTRAINT as well as UNIQUE INDEX.
940
706
 
941
- ```ruby
942
- ActiveRecord.schema_cache_ignored_tables = ["developers"]
943
- ActiveRecord.schema_cache_ignored_table?("developers")
944
- => true
945
- ```
707
+ *Ryuta Kamizono*
946
708
 
947
- *Eileen M. Uchitelle*
709
+ * `PG::UnableToSend: no connection to the server` is now retryable as a connection-related exception
710
+
711
+ *Kazuma Watanabe*
948
712
 
949
- Please check [7-2-stable](https://github.com/rails/rails/blob/7-2-stable/activerecord/CHANGELOG.md) for previous changes.
713
+ Please check [8-0-stable](https://github.com/rails/rails/blob/8-0-stable/activerecord/CHANGELOG.md) for previous changes.