activerecord 7.0.10 → 7.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.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (228) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1348 -1672
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +15 -17
  5. data/lib/active_record/aggregations.rb +16 -13
  6. data/lib/active_record/association_relation.rb +1 -1
  7. data/lib/active_record/associations/association.rb +18 -3
  8. data/lib/active_record/associations/association_scope.rb +16 -9
  9. data/lib/active_record/associations/belongs_to_association.rb +14 -6
  10. data/lib/active_record/associations/builder/association.rb +3 -3
  11. data/lib/active_record/associations/builder/belongs_to.rb +21 -8
  12. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
  13. data/lib/active_record/associations/builder/singular_association.rb +4 -0
  14. data/lib/active_record/associations/collection_association.rb +17 -9
  15. data/lib/active_record/associations/collection_proxy.rb +16 -11
  16. data/lib/active_record/associations/foreign_association.rb +10 -3
  17. data/lib/active_record/associations/has_many_association.rb +20 -13
  18. data/lib/active_record/associations/has_many_through_association.rb +10 -6
  19. data/lib/active_record/associations/has_one_association.rb +10 -3
  20. data/lib/active_record/associations/join_dependency.rb +10 -8
  21. data/lib/active_record/associations/preloader/association.rb +27 -6
  22. data/lib/active_record/associations/preloader.rb +12 -9
  23. data/lib/active_record/associations/singular_association.rb +1 -1
  24. data/lib/active_record/associations/through_association.rb +22 -11
  25. data/lib/active_record/associations.rb +313 -217
  26. data/lib/active_record/attribute_assignment.rb +0 -2
  27. data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
  28. data/lib/active_record/attribute_methods/dirty.rb +48 -38
  29. data/lib/active_record/attribute_methods/primary_key.rb +76 -24
  30. data/lib/active_record/attribute_methods/query.rb +28 -16
  31. data/lib/active_record/attribute_methods/read.rb +18 -5
  32. data/lib/active_record/attribute_methods/serialization.rb +150 -31
  33. data/lib/active_record/attribute_methods/write.rb +3 -3
  34. data/lib/active_record/attribute_methods.rb +105 -21
  35. data/lib/active_record/attributes.rb +3 -3
  36. data/lib/active_record/autosave_association.rb +55 -9
  37. data/lib/active_record/base.rb +7 -2
  38. data/lib/active_record/callbacks.rb +10 -24
  39. data/lib/active_record/coders/column_serializer.rb +61 -0
  40. data/lib/active_record/coders/json.rb +1 -1
  41. data/lib/active_record/coders/yaml_column.rb +70 -42
  42. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +163 -88
  43. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
  44. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +3 -1
  45. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +65 -49
  46. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
  47. data/lib/active_record/connection_adapters/abstract/database_statements.rb +109 -32
  48. data/lib/active_record/connection_adapters/abstract/query_cache.rb +60 -22
  49. data/lib/active_record/connection_adapters/abstract/quoting.rb +41 -6
  50. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  51. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
  52. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -11
  53. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +291 -122
  54. data/lib/active_record/connection_adapters/abstract/transaction.rb +280 -58
  55. data/lib/active_record/connection_adapters/abstract_adapter.rb +502 -91
  56. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +200 -115
  57. data/lib/active_record/connection_adapters/column.rb +9 -0
  58. data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
  59. data/lib/active_record/connection_adapters/mysql/database_statements.rb +22 -143
  60. data/lib/active_record/connection_adapters/mysql/quoting.rb +16 -12
  61. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
  62. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +6 -0
  63. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
  64. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +18 -14
  65. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +148 -0
  66. data/lib/active_record/connection_adapters/mysql2_adapter.rb +98 -53
  67. data/lib/active_record/connection_adapters/pool_config.rb +14 -5
  68. data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
  69. data/lib/active_record/connection_adapters/postgresql/column.rb +1 -2
  70. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +76 -29
  71. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -3
  72. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
  73. data/lib/active_record/connection_adapters/postgresql/quoting.rb +9 -6
  74. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -9
  75. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
  76. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +131 -2
  77. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +42 -0
  78. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +352 -55
  79. data/lib/active_record/connection_adapters/postgresql_adapter.rb +336 -168
  80. data/lib/active_record/connection_adapters/schema_cache.rb +287 -59
  81. data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
  82. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +42 -36
  83. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +4 -3
  84. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +1 -0
  85. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +26 -7
  86. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +162 -77
  87. data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
  88. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +98 -0
  89. data/lib/active_record/connection_adapters/trilogy_adapter.rb +254 -0
  90. data/lib/active_record/connection_adapters.rb +3 -1
  91. data/lib/active_record/connection_handling.rb +72 -95
  92. data/lib/active_record/core.rb +131 -142
  93. data/lib/active_record/counter_cache.rb +46 -25
  94. data/lib/active_record/database_configurations/database_config.rb +9 -3
  95. data/lib/active_record/database_configurations/hash_config.rb +22 -12
  96. data/lib/active_record/database_configurations/url_config.rb +17 -11
  97. data/lib/active_record/database_configurations.rb +86 -33
  98. data/lib/active_record/delegated_type.rb +11 -6
  99. data/lib/active_record/deprecator.rb +7 -0
  100. data/lib/active_record/destroy_association_async_job.rb +2 -0
  101. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  102. data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
  103. data/lib/active_record/encryption/config.rb +25 -1
  104. data/lib/active_record/encryption/configurable.rb +12 -19
  105. data/lib/active_record/encryption/context.rb +10 -3
  106. data/lib/active_record/encryption/contexts.rb +5 -1
  107. data/lib/active_record/encryption/derived_secret_key_provider.rb +8 -2
  108. data/lib/active_record/encryption/encryptable_record.rb +36 -18
  109. data/lib/active_record/encryption/encrypted_attribute_type.rb +17 -6
  110. data/lib/active_record/encryption/extended_deterministic_queries.rb +52 -12
  111. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +2 -2
  112. data/lib/active_record/encryption/key_generator.rb +12 -1
  113. data/lib/active_record/encryption/message_serializer.rb +2 -0
  114. data/lib/active_record/encryption/properties.rb +3 -3
  115. data/lib/active_record/encryption/scheme.rb +19 -22
  116. data/lib/active_record/encryption.rb +1 -0
  117. data/lib/active_record/enum.rb +113 -26
  118. data/lib/active_record/errors.rb +89 -15
  119. data/lib/active_record/explain.rb +23 -3
  120. data/lib/active_record/fixture_set/model_metadata.rb +14 -4
  121. data/lib/active_record/fixture_set/render_context.rb +2 -0
  122. data/lib/active_record/fixture_set/table_row.rb +29 -8
  123. data/lib/active_record/fixtures.rb +119 -83
  124. data/lib/active_record/future_result.rb +30 -5
  125. data/lib/active_record/gem_version.rb +4 -4
  126. data/lib/active_record/inheritance.rb +30 -16
  127. data/lib/active_record/insert_all.rb +58 -11
  128. data/lib/active_record/integration.rb +8 -8
  129. data/lib/active_record/internal_metadata.rb +118 -30
  130. data/lib/active_record/locking/pessimistic.rb +5 -2
  131. data/lib/active_record/log_subscriber.rb +29 -12
  132. data/lib/active_record/marshalling.rb +56 -0
  133. data/lib/active_record/message_pack.rb +124 -0
  134. data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
  135. data/lib/active_record/middleware/database_selector.rb +6 -8
  136. data/lib/active_record/middleware/shard_selector.rb +3 -1
  137. data/lib/active_record/migration/command_recorder.rb +100 -4
  138. data/lib/active_record/migration/compatibility.rb +131 -5
  139. data/lib/active_record/migration/default_strategy.rb +23 -0
  140. data/lib/active_record/migration/execution_strategy.rb +19 -0
  141. data/lib/active_record/migration.rb +215 -112
  142. data/lib/active_record/model_schema.rb +50 -32
  143. data/lib/active_record/nested_attributes.rb +31 -6
  144. data/lib/active_record/normalization.rb +158 -0
  145. data/lib/active_record/persistence.rb +183 -33
  146. data/lib/active_record/promise.rb +84 -0
  147. data/lib/active_record/query_cache.rb +3 -21
  148. data/lib/active_record/query_logs.rb +77 -52
  149. data/lib/active_record/query_logs_formatter.rb +41 -0
  150. data/lib/active_record/querying.rb +15 -2
  151. data/lib/active_record/railtie.rb +108 -46
  152. data/lib/active_record/railties/controller_runtime.rb +10 -5
  153. data/lib/active_record/railties/databases.rake +139 -145
  154. data/lib/active_record/railties/job_runtime.rb +23 -0
  155. data/lib/active_record/readonly_attributes.rb +32 -5
  156. data/lib/active_record/reflection.rb +169 -45
  157. data/lib/active_record/relation/batches/batch_enumerator.rb +5 -3
  158. data/lib/active_record/relation/batches.rb +190 -61
  159. data/lib/active_record/relation/calculations.rb +152 -63
  160. data/lib/active_record/relation/delegation.rb +23 -9
  161. data/lib/active_record/relation/finder_methods.rb +85 -15
  162. data/lib/active_record/relation/merger.rb +2 -0
  163. data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -2
  164. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  165. data/lib/active_record/relation/predicate_builder.rb +26 -14
  166. data/lib/active_record/relation/query_attribute.rb +2 -1
  167. data/lib/active_record/relation/query_methods.rb +351 -62
  168. data/lib/active_record/relation/spawn_methods.rb +18 -1
  169. data/lib/active_record/relation.rb +75 -34
  170. data/lib/active_record/result.rb +19 -5
  171. data/lib/active_record/runtime_registry.rb +10 -1
  172. data/lib/active_record/sanitization.rb +51 -11
  173. data/lib/active_record/schema.rb +2 -3
  174. data/lib/active_record/schema_dumper.rb +41 -7
  175. data/lib/active_record/schema_migration.rb +68 -33
  176. data/lib/active_record/scoping/default.rb +15 -5
  177. data/lib/active_record/scoping/named.rb +2 -2
  178. data/lib/active_record/scoping.rb +2 -1
  179. data/lib/active_record/secure_password.rb +60 -0
  180. data/lib/active_record/secure_token.rb +21 -3
  181. data/lib/active_record/signed_id.rb +7 -5
  182. data/lib/active_record/store.rb +8 -8
  183. data/lib/active_record/suppressor.rb +3 -1
  184. data/lib/active_record/table_metadata.rb +10 -1
  185. data/lib/active_record/tasks/database_tasks.rb +127 -105
  186. data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
  187. data/lib/active_record/tasks/postgresql_database_tasks.rb +16 -13
  188. data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -7
  189. data/lib/active_record/test_fixtures.rb +113 -96
  190. data/lib/active_record/timestamp.rb +27 -15
  191. data/lib/active_record/token_for.rb +113 -0
  192. data/lib/active_record/touch_later.rb +11 -6
  193. data/lib/active_record/transactions.rb +36 -10
  194. data/lib/active_record/type/adapter_specific_registry.rb +1 -8
  195. data/lib/active_record/type/internal/timezone.rb +7 -2
  196. data/lib/active_record/type/time.rb +4 -0
  197. data/lib/active_record/validations/absence.rb +1 -1
  198. data/lib/active_record/validations/numericality.rb +5 -4
  199. data/lib/active_record/validations/presence.rb +5 -28
  200. data/lib/active_record/validations/uniqueness.rb +47 -2
  201. data/lib/active_record/validations.rb +8 -4
  202. data/lib/active_record/version.rb +1 -1
  203. data/lib/active_record.rb +121 -16
  204. data/lib/arel/errors.rb +10 -0
  205. data/lib/arel/factory_methods.rb +4 -0
  206. data/lib/arel/nodes/binary.rb +6 -1
  207. data/lib/arel/nodes/bound_sql_literal.rb +61 -0
  208. data/lib/arel/nodes/cte.rb +36 -0
  209. data/lib/arel/nodes/fragments.rb +35 -0
  210. data/lib/arel/nodes/homogeneous_in.rb +1 -9
  211. data/lib/arel/nodes/leading_join.rb +8 -0
  212. data/lib/arel/nodes/node.rb +111 -2
  213. data/lib/arel/nodes/sql_literal.rb +6 -0
  214. data/lib/arel/nodes/table_alias.rb +4 -0
  215. data/lib/arel/nodes.rb +4 -0
  216. data/lib/arel/predications.rb +2 -0
  217. data/lib/arel/table.rb +9 -5
  218. data/lib/arel/visitors/mysql.rb +8 -1
  219. data/lib/arel/visitors/to_sql.rb +81 -17
  220. data/lib/arel/visitors/visitor.rb +2 -2
  221. data/lib/arel.rb +16 -2
  222. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  223. data/lib/rails/generators/active_record/migration.rb +3 -1
  224. data/lib/rails/generators/active_record/model/USAGE +113 -0
  225. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  226. metadata +52 -14
  227. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  228. data/lib/active_record/null_relation.rb +0 -63
data/CHANGELOG.md CHANGED
@@ -1,134 +1,66 @@
1
- ## Rails 7.0.10 (October 28, 2025) ##
1
+ ## Rails 7.1.0.beta1 (September 13, 2023) ##
2
2
 
3
- * No changes.
3
+ * Encryption now supports `support_unencrypted_data` being set per-attribute.
4
4
 
5
-
6
- ## Rails 7.0.9 (October 28, 2025) ##
7
-
8
- * Fix an issue that could cause database connection leaks
9
-
10
- If Active Record successfully connected to the database, but then failed
11
- to read the server informations, the connection would be leaked until the
12
- Ruby garbage collector triggers.
13
-
14
- *Jean Boussier*
15
-
16
- * Fix single quote escapes on default generated MySQL columns
17
-
18
- MySQL 5.7.5+ supports generated columns, which can be used to create a column that is computed from an expression.
19
-
20
- Previously, the schema dump would output a string with double escapes for generated columns with single quotes in the default expression.
21
-
22
- This would result in issues when importing the schema on a fresh instance of a MySQL database.
23
-
24
- Now, the string will not be escaped and will be valid Ruby upon importing of the schema.
25
-
26
- *Yash Kapadia*
27
-
28
- * Fix `Relation#transaction` to not apply a default scope
29
-
30
- The method was incorrectly setting a default scope around its block:
5
+ You can now opt out of `support_unencrypted_data` on a specific encrypted attribute.
6
+ This only has an effect if `ActiveRecord::Encryption.config.support_unencrypted_data == true`.
31
7
 
32
8
  ```ruby
33
- Post.where(published: true).transaction do
34
- Post.count # SELECT COUNT(*) FROM posts WHERE published = FALSE;
9
+ class User < ActiveRecord::Base
10
+ encrypts :name, deterministic: true, support_unencrypted_data: false
11
+ encrypts :email, deterministic: true
35
12
  end
36
13
  ```
37
14
 
38
- *Jean Boussier*
39
-
40
- * Fix renaming primary key index when renaming a table with a UUID primary key
41
- in PostgreSQL.
42
-
43
- *fatkodima*
44
-
45
- * Fix `where(field: values)` queries when `field` is a serialized attribute
46
- (for example, when `field` uses `ActiveRecord::Base.serialize` or is a JSON
47
- column).
48
-
49
- *João Alves*
50
-
51
- * Don't mark Float::INFINITY as changed when reassigning it
52
-
53
- When saving a record with a float infinite value, it shouldn't mark as changed
54
-
55
- *Maicol Bentancor*
56
-
57
- * `ActiveRecord::Base.table_name` now returns `nil` instead of raising
58
- "undefined method `abstract_class?` for Object:Class".
59
-
60
- *a5-stable*
61
-
62
- * Fix upserting for custom `:on_duplicate` and `:unique_by` consisting of all
63
- inserts keys.
64
-
65
- *fatkodima*
66
-
67
- * Fix `NoMethodError` when casting a PostgreSQL `money` value that uses a
68
- comma as its radix point and has no leading currency symbol. For example,
69
- when casting `"3,50"`.
15
+ *Alex Ghiculescu*
70
16
 
71
- *Andreas Reischuck* and *Jonathan Hefner*
17
+ * Add instrumentation for Active Record transactions
72
18
 
73
- * Fix duplicate quoting for check constraint expressions in schema dump when using MySQL
19
+ Allows subscribing to transaction events for tracking/instrumentation. The event payload contains the connection, as well as timing details.
74
20
 
75
- A check constraint with an expression, that already contains quotes, lead to an invalid schema
76
- dump with the mysql2 adapter.
21
+ ```ruby
22
+ ActiveSupport::Notifications.subscribe("transaction.active_record") do |event|
23
+ puts "Transaction event occurred!"
24
+ connection = event.payload[:connection]
25
+ puts "Connection: #{connection.inspect}"
26
+ end
27
+ ```
77
28
 
78
- Fixes #42424.
29
+ *Daniel Colson*, *Ian Candy*
79
30
 
80
- *Felix Tscheulin*
31
+ * Support composite foreign keys via migration helpers.
81
32
 
82
- * Fix MySQL expression index dumping with escaped quotes.
33
+ ```ruby
34
+ # Assuming "carts" table has "(shop_id, user_id)" as a primary key.
83
35
 
84
- *fatkodima*
36
+ add_foreign_key(:orders, :carts, primary_key: [:shop_id, :user_id])
85
37
 
86
- * Fix uniqueness validation on association not using overridden primary key.
38
+ remove_foreign_key(:orders, :carts, primary_key: [:shop_id, :user_id])
39
+ foreign_key_exists?(:orders, :carts, primary_key: [:shop_id, :user_id])
40
+ ```
87
41
 
88
42
  *fatkodima*
89
43
 
44
+ * Adds support for `if_not_exists` when adding a check constraint.
90
45
 
91
- ## Rails 7.0.8.7 (December 10, 2024) ##
92
-
93
- * No changes.
94
-
95
-
96
- ## Rails 7.0.8.6 (October 23, 2024) ##
97
-
98
- * No changes.
99
-
100
-
101
- ## Rails 7.0.8.5 (October 15, 2024) ##
102
-
103
- * No changes.
104
-
105
-
106
- ## Rails 7.0.8.4 (June 04, 2024) ##
107
-
108
- * No changes.
109
-
110
-
111
- ## Rails 7.0.8.3 (May 17, 2024) ##
112
-
113
- * No changes.
114
-
115
-
116
- ## Rails 7.0.8.2 (May 16, 2024) ##
117
-
118
- * No changes.
46
+ ```ruby
47
+ add_check_constraint :posts, "post_type IN ('blog', 'comment', 'share')", if_not_exists: true
48
+ ```
119
49
 
50
+ *Cody Cutrer*
120
51
 
121
- ## Rails 7.0.8.1 (February 21, 2024) ##
52
+ * Raise an `ArgumentError` when `#accepts_nested_attributes_for` is declared more than once for an association in
53
+ the same class. Previously, the last declaration would silently override the previous one. Overriding in a subclass
54
+ is still allowed.
122
55
 
123
- * No changes.
56
+ *Joshua Young*
124
57
 
58
+ * Deprecate `rewhere` argument on `#merge`.
125
59
 
126
- ## Rails 7.0.8 (September 09, 2023) ##
60
+ The `rewhere` argument on `#merge`is deprecated without replacement and
61
+ will be removed in Rails 7.2.
127
62
 
128
- * Fix `change_column` not setting `precision: 6` on `datetime` columns when
129
- using 7.0+ Migrations and SQLite.
130
-
131
- *Hartley McGuire*
63
+ *Adam Hess*
132
64
 
133
65
  * Fix unscope is not working in specific case
134
66
 
@@ -147,83 +79,96 @@
147
79
 
148
80
  *Kazuya Hatanaka*
149
81
 
150
- * Fix associations to a STI model including a `class_name` parameter
82
+ * Change `has_secure_token` default to `on: :initialize`
83
+
84
+ Change the new default value from `on: :create` to `on: :initialize`
85
+
86
+ Can be controlled by the `config.active_record.generate_secure_token_on`
87
+ configuration:
151
88
 
152
89
  ```ruby
153
- class Product < ApplicationRecord
154
- has_many :requests, as: :requestable, class_name: "ProductRequest", dependent: :destroy
155
- end
90
+ config.active_record.generate_secure_token_on = :create
91
+ ```
156
92
 
157
- # STI tables
158
- class Request < ApplicationRecord
159
- belongs_to :requestable, polymorphic: true
93
+ *Sean Doyle*
160
94
 
161
- validate :request_type, presence: true
162
- end
95
+ * Fix `change_column` not setting `precision: 6` on `datetime` columns when
96
+ using 7.0+ Migrations and SQLite.
163
97
 
164
- class ProductRequest < Request
165
- belongs_to :user
166
- end
167
- ```
98
+ *Hartley McGuire*
168
99
 
169
- Accessing such association would lead to:
100
+ * Support composite identifiers in `to_key`
170
101
 
171
- ```
172
- table_metadata.rb:22:in `has_column?': undefined method `key?' for nil:NilClass (NoMethodError)
173
- ```
102
+ `to_key` avoids wrapping `#id` value into an `Array` if `#id` already an array
174
103
 
175
- *Romain Filinto*
104
+ *Nikita Vasilevsky*
176
105
 
177
- * Fix `change_table` setting datetime precision for 6.1 Migrations
106
+ * Add validation option for `enum`
178
107
 
179
- *Hartley McGuire*
108
+ ```ruby
109
+ class Contract < ApplicationRecord
110
+ enum :status, %w[in_progress completed], validate: true
111
+ end
112
+ Contract.new(status: "unknown").valid? # => false
113
+ Contract.new(status: nil).valid? # => false
114
+ Contract.new(status: "completed").valid? # => true
180
115
 
181
- * Fix change_column setting datetime precision for 6.1 Migrations
116
+ class Contract < ApplicationRecord
117
+ enum :status, %w[in_progress completed], validate: { allow_nil: true }
118
+ end
119
+ Contract.new(status: "unknown").valid? # => false
120
+ Contract.new(status: nil).valid? # => true
121
+ Contract.new(status: "completed").valid? # => true
122
+ ```
182
123
 
183
- *Hartley McGuire*
124
+ *Edem Topuzov*, *Ryuta Kamizono*
184
125
 
185
- ## Rails 7.0.7.2 (August 22, 2023) ##
126
+ * Allow batching methods to use already loaded relation if available
186
127
 
187
- * No changes.
128
+ Calling batch methods on already loaded relations will use the records previously loaded instead of retrieving
129
+ them from the database again.
188
130
 
131
+ *Adam Hess*
189
132
 
190
- ## Rails 7.0.7.1 (August 22, 2023) ##
133
+ * Deprecate `read_attribute(:id)` returning the primary key if the primary key is not `:id`.
191
134
 
192
- * No changes.
135
+ Starting in Rails 7.2, `read_attribute(:id)` will return the value of the id column, regardless of the model's
136
+ primary key. To retrieve the value of the primary key, use `#id` instead. `read_attribute(:id)` for composite
137
+ primary key models will now return the value of the id column.
193
138
 
139
+ *Adrianna Chang*
194
140
 
195
- ## Rails 7.0.7 (August 09, 2023) ##
141
+ * Fix `change_table` setting datetime precision for 6.1 Migrations
196
142
 
197
- * Restores functionality to the missing method when using enums and fixes.
143
+ *Hartley McGuire*
198
144
 
199
- *paulreece*
145
+ * Fix change_column setting datetime precision for 6.1 Migrations
200
146
 
201
- * Fix `StatementCache::Substitute` with serialized type.
147
+ *Hartley McGuire*
202
148
 
203
- *ywenc*
149
+ * Add `ActiveRecord::Base#id_value` alias to access the raw value of a record's id column.
204
150
 
205
- * Fix `:db_runtime` on notification payload when application have multiple databases.
151
+ This alias is only provided for models that declare an `:id` column.
206
152
 
207
- *Eileen M. Uchitelle*
153
+ *Adrianna Chang*
208
154
 
209
- * Correctly dump check constraints for MySQL 8.0.16+.
155
+ * Fix previous change tracking for `ActiveRecord::Store` when using a column with JSON structured database type
210
156
 
211
- *Steve Hill*
157
+ Before, the methods to access the changes made during the last save `#saved_change_to_key?`, `#saved_change_to_key`, and `#key_before_last_save` did not work if the store was defined as a `store_accessor` on a column with a JSON structured database type
212
158
 
213
- * Fix `ActiveRecord::QueryMethods#in_order_of` to include `nil`s, to match the
214
- behavior of `Enumerable#in_order_of`.
159
+ *Robert DiMartino*
215
160
 
216
- For example, `Post.in_order_of(:title, [nil, "foo"])` will now include posts
217
- with `nil` titles, the same as `Post.all.to_a.in_order_of(:title, [nil, "foo"])`.
161
+ * Fully support `NULLS [NOT] DISTINCT` for PostgreSQL 15+ indexes.
218
162
 
219
- *fatkodima*
163
+ Previous work was done to allow the index to be created in a migration, but it was not
164
+ supported in schema.rb. Additionally, the matching for `NULLS [NOT] DISTINCT` was not
165
+ in the correct order, which could have resulted in inconsistent schema detection.
220
166
 
221
- * Revert "Fix autosave associations with validations added on `:base` of the associated objects."
167
+ *Gregory Jones*
222
168
 
223
- This change intended to remove the :base attribute from the message,
224
- but broke many assumptions which key these errors were stored.
169
+ * Allow escaping of literal colon characters in `sanitize_sql_*` methods when named bind variables are used
225
170
 
226
- *zzak*
171
+ *Justin Bull*
227
172
 
228
173
  * Fix `#previously_new_record?` to return true for destroyed records.
229
174
 
@@ -233,2270 +178,2001 @@
233
178
 
234
179
  *Adrianna Chang*
235
180
 
236
- * Revert breaking changes to `has_one` relationship deleting the old record before the new one is validated.
237
-
238
- *zzak*
239
-
240
- * Fix support for Active Record instances being uses in queries.
241
-
242
- As of `7.0.5`, query arguments were deep duped to avoid mutations impacting
243
- the query cache, but this had the adverse effect to clearing the primary key when
244
- the query argument contained an `ActiveRecord::Base` instance.
245
-
246
- This broke the `noticed` gem.
247
-
248
- *Jean Boussier*
249
-
250
-
251
- ## Rails 7.0.6 (June 29, 2023) ##
252
-
253
- * Fix autosave associations with validations added on `:base` of the associated objects.
254
-
255
- *fatkodima*
181
+ * Specify callback in `has_secure_token`
256
182
 
257
- * Fix result with anonymous PostgreSQL columns of different type from json.
183
+ ```ruby
184
+ class User < ApplicationRecord
185
+ has_secure_token on: :initialize
186
+ end
258
187
 
259
- *Oleksandr Avoiants*
188
+ User.new.token # => "abc123...."
189
+ ```
260
190
 
261
- * Preserve timestamp when setting an `ActiveSupport::TimeWithZone` value to `timestamptz` attribute.
191
+ *Sean Doyle*
262
192
 
263
- *fatkodima*
193
+ * Fix incrementation of in memory counter caches when associations overlap
264
194
 
265
- * Fix assignment into an `has_one` relationship deleting the old record before the new one is validated.
195
+ When two associations had a similarly named counter cache column, Active Record
196
+ could sometime increment the wrong one.
266
197
 
267
- *Jean Boussier*
198
+ *Jacopo Beschi*, *Jean Boussier*
268
199
 
269
- * Fix where on association with has_one/has_many polymorphic relations.
200
+ * Don't show secrets for Active Record's `Cipher::Aes256Gcm#inspect`.
270
201
 
271
202
  Before:
272
- ```ruby
273
- Treasure.where(price_estimates: PriceEstimate.all)
274
- #=> SELECT (...) WHERE "treasures"."id" IN (SELECT "price_estimates"."estimate_of_id" FROM "price_estimates")
275
- ```
276
203
 
277
- Later:
278
204
  ```ruby
279
- Treasure.where(price_estimates: PriceEstimate.all)
280
- #=> SELECT (...) WHERE "treasures"."id" IN (SELECT "price_estimates"."estimate_of_id" FROM "price_estimates" WHERE "price_estimates"."estimate_of_type" = 'Treasure')
205
+ ActiveRecord::Encryption::Cipher::Aes256Gcm.new(secret).inspect
206
+ "#<ActiveRecord::Encryption::Cipher::Aes256Gcm:0x0000000104888038 ... @secret=\"\\xAF\\bFh]LV}q\\nl\\xB2U\\xB3 ... >"
281
207
  ```
282
208
 
283
- *Lázaro Nixon*
284
-
285
- * Fix decrementing counter caches on optimistically locked record deletion
286
-
287
- *fatkodima*
288
-
289
- * Ensure binary-destined values have binary encoding during type cast.
290
-
291
- *Matthew Draper*
292
-
293
- * Preserve existing column default functions when altering table in SQLite.
294
-
295
- *fatkodima*
296
-
297
- * Remove table alias added when using `where.missing` or `where.associated`.
298
-
299
- *fatkodima*
300
-
301
- * Fix `Enumerable#in_order_of` to only flatten first level to preserve nesting.
302
-
303
- *Miha Rekar*
304
-
305
-
306
- ## Rails 7.0.5.1 (June 26, 2023) ##
307
-
308
- * No changes.
309
-
310
- ## Rails 7.0.5 (May 24, 2023) ##
311
-
312
- * Type cast `#attribute_changed?` `:from` and `:to` options.
313
-
314
- *Andrew Novoselac*
315
-
316
- * Fix `index_exists?` when column is an array.
317
-
318
- *Eileen M. Uchitelle*
319
-
320
- * Handle `Date` objects for PostgreSQL `timestamptz` columns.
321
-
322
- *Alex Ghiculescu*
323
-
324
- * Fix collation for changing column to non-string.
325
-
326
- *Hartley McGuire*
327
-
328
- * Map through subtype in `PostgreSQL::OID::Array`.
329
-
330
- *Jonathan Hefner*
331
-
332
- * Store correct environment in `internal_metadata` when run rails `db:prepare`.
333
-
334
- *fatkodima*
335
-
336
- * Make sure `ActiveRecord::Relation#sum` works with objects that implement `#coerce` without deprecation.
337
-
338
- *Alex Ghiculescu*
339
-
340
- * Fix retrieving foreign keys referencing tables named like keywords in PostgreSQL and MySQL.
341
-
342
- *fatkodima*
343
-
344
- * Support UUIDs in Disable Joins.
345
-
346
- *Samuel Cochran*
347
-
348
- * Fix Active Record's explain for queries starting with comments.
349
-
350
- *fatkodima*
351
-
352
- * Fix incorrectly preloading through association records when middle association has been loaded.
353
-
354
- *Joshua Young*
355
-
356
- * Fix where.missing and where.associated for parent/child associations.
357
-
358
- *fatkodima*
209
+ After:
359
210
 
360
- * Fix Enumerable#in_order_of to preserve duplicates.
211
+ ```ruby
212
+ ActiveRecord::Encryption::Cipher::Aes256Gcm(secret).inspect
213
+ "#<ActiveRecord::Encryption::Cipher::Aes256Gcm:0x0000000104888038>"
214
+ ```
361
215
 
362
- *fatkodima*
216
+ *Petrik de Heus*
363
217
 
364
- * Fix autoincrement on primary key for mysql.
218
+ * Bring back the historical behavior of committing transaction on non-local return.
365
219
 
366
- *Eileen M. Uchitelle*
220
+ ```ruby
221
+ Model.transaction do
222
+ model.save
223
+ return
224
+ other_model.save # not executed
225
+ end
226
+ ```
367
227
 
368
- * Restore ability to redefine column in `create_table` for Rails 5.2 migrations.
228
+ Historically only raised errors would trigger a rollback, but in Ruby `2.3`, the `timeout` library
229
+ started using `throw` to interrupt execution which had the adverse effect of committing open transactions.
369
230
 
370
- *fatkodima*
231
+ To solve this, in Active Record 6.1 the behavior was changed to instead rollback the transaction as it was safer
232
+ than to potentially commit an incomplete transaction.
371
233
 
372
- * Fix schema cache dumping of virtual columns.
234
+ Using `return`, `break` or `throw` inside a `transaction` block was essentially deprecated from Rails 6.1 onwards.
373
235
 
374
- *fatkodima*
236
+ However with the release of `timeout 0.4.0`, `Timeout.timeout` now raises an error again, and Active Record is able
237
+ to return to its original, less surprising, behavior.
375
238
 
376
- * Fix Active Record grouped calculations on joined tables on column present in both tables.
239
+ This historical behavior can now be opt-ed in via:
377
240
 
378
- *fatkodima*
241
+ ```
242
+ Rails.application.config.active_record.commit_transaction_on_non_local_return = true
243
+ ```
379
244
 
380
- * Fix mutation detection for serialized attributes backed by binary columns.
245
+ And is the default for new applications created in Rails 7.1.
381
246
 
382
247
  *Jean Boussier*
383
248
 
384
- * Fix a bug where using groups and counts with long table names would return incorrect results.
249
+ * Deprecate `name` argument on `#remove_connection`.
385
250
 
386
- *Shota Toguchi*, *Yusaku Ono*
251
+ The `name` argument is deprecated on `#remove_connection` without replacement. `#remove_connection` should be called directly on the class that established the connection.
387
252
 
388
- * Fix erroneous nil default precision on virtual datetime columns.
389
-
390
- Prior to this change, virtual datetime columns did not have the same
391
- default precision as regular datetime columns, resulting in the following
392
- being erroneously equivalent:
393
-
394
- t.virtual :name, type: datetime, as: "expression"
395
- t.virtual :name, type: datetime, precision: nil, as: "expression"
396
-
397
- This change fixes the default precision lookup, so virtual and regular
398
- datetime column default precisions match.
399
-
400
- *Sam Bostock*
401
-
402
- * Fix a case where the query cache can return wrong values. See #46044
403
-
404
- *Aaron Patterson*
405
-
406
-
407
- ## Rails 7.0.4.3 (March 13, 2023) ##
408
-
409
- * No changes.
410
-
411
-
412
- ## Rails 7.0.4.2 (January 24, 2023) ##
413
-
414
- * No changes.
415
-
416
-
417
- ## Rails 7.0.4.1 (January 17, 2023) ##
418
-
419
- * Make sanitize_as_sql_comment more strict
420
-
421
- Though this method was likely never meant to take user input, it was
422
- attempting sanitization. That sanitization could be bypassed with
423
- carefully crafted input.
424
-
425
- This commit makes the sanitization more robust by replacing any
426
- occurrences of "/*" or "*/" with "/ *" or "* /". It also performs a
427
- first pass to remove one surrounding comment to avoid compatibility
428
- issues for users relying on the existing removal.
429
-
430
- This also clarifies in the documentation of annotate that it should not
431
- be provided user input.
432
-
433
- [CVE-2023-22794]
253
+ *Eileen M. Uchitelle*
434
254
 
435
- * Added integer width check to PostgreSQL::Quoting
255
+ * Fix has_one through singular building with inverse.
436
256
 
437
- Given a value outside the range for a 64bit signed integer type
438
- PostgreSQL will treat the column type as numeric. Comparing
439
- integer values against numeric values can result in a slow
440
- sequential scan.
257
+ Allows building of records from an association with a has_one through a
258
+ singular association with inverse. For belongs_to through associations,
259
+ linking the foreign key to the primary key model isn't needed.
260
+ For has_one, we cannot build records due to the association not being mutable.
441
261
 
442
- This behavior is configurable via
443
- ActiveRecord::Base.raise_int_wider_than_64bit which defaults to true.
262
+ *Gannon McGibbon*
444
263
 
445
- [CVE-2022-44566]
264
+ * Disable database prepared statements when query logs are enabled
446
265
 
266
+ Prepared Statements and Query Logs are incompatible features due to query logs making every query unique.
447
267
 
448
- ## Rails 7.0.4 (September 09, 2022) ##
268
+ *zzak, Jean Boussier*
449
269
 
450
- * Symbol is allowed by default for YAML columns
270
+ * Support decrypting data encrypted non-deterministically with a SHA1 hash digest.
451
271
 
452
- *Étienne Barrié*
272
+ This adds a new Active Record encryption option to support decrypting data encrypted
273
+ non-deterministically with a SHA1 hash digest:
453
274
 
454
- * Fix `ActiveRecord::Store` to serialize as a regular Hash
455
-
456
- Previously it would serialize as an `ActiveSupport::HashWithIndifferentAccess`
457
- which is wasteful and cause problem with YAML safe_load.
275
+ ```
276
+ Rails.application.config.active_record.encryption.support_sha1_for_non_deterministic_encryption = true
277
+ ```
458
278
 
459
- *Jean Boussier*
279
+ The new option addresses a problem when upgrading from 7.0 to 7.1. Due to a bug in how Active Record
280
+ Encryption was getting initialized, the key provider used for non-deterministic encryption were using
281
+ SHA-1 as its digest class, instead of the one configured globally by Rails via
282
+ `Rails.application.config.active_support.key_generator_hash_digest_class`.
460
283
 
461
- * Add `timestamptz` as a time zone aware type for PostgreSQL
284
+ *Cadu Ribeiro and Jorge Manrubia*
462
285
 
463
- This is required for correctly parsing `timestamp with time zone` values in your database.
286
+ * Added PostgreSQL migration commands for enum rename, add value, and rename value.
464
287
 
465
- If you don't want this, you can opt out by adding this initializer:
288
+ `rename_enum` and `rename_enum_value` are reversible. Due to Postgres
289
+ limitation, `add_enum_value` is not reversible since you cannot delete enum
290
+ values. As an alternative you should drop and recreate the enum entirely.
466
291
 
467
292
  ```ruby
468
- ActiveRecord::Base.time_zone_aware_types -= [:timestamptz]
293
+ rename_enum :article_status, to: :article_state
469
294
  ```
470
295
 
471
- *Alex Ghiculescu*
472
-
473
- * Fix supporting timezone awareness for `tsrange` and `tstzrange` array columns.
474
-
475
296
  ```ruby
476
- # In database migrations
477
- add_column :shops, :open_hours, :tsrange, array: true
478
- # In app config
479
- ActiveRecord::Base.time_zone_aware_types += [:tsrange]
480
- # In the code times are properly converted to app time zone
481
- Shop.create!(open_hours: [Time.current..8.hour.from_now])
297
+ add_enum_value :article_state, "archived" # will be at the end of existing values
298
+ add_enum_value :article_state, "in review", before: "published"
299
+ add_enum_value :article_state, "approved", after: "in review"
482
300
  ```
483
301
 
484
- *Wojciech Wnętrzak*
485
-
486
- * Resolve issue where a relation cache_version could be left stale.
487
-
488
- Previously, when `reset` was called on a relation object it did not reset the cache_versions
489
- ivar. This led to a confusing situation where despite having the correct data the relation
490
- still reported a stale cache_version.
491
-
492
- Usage:
493
-
494
302
  ```ruby
495
- developers = Developer.all
496
- developers.cache_version
497
-
498
- Developer.update_all(updated_at: Time.now.utc + 1.second)
499
-
500
- developers.cache_version # Stale cache_version
501
- developers.reset
502
- developers.cache_version # Returns the current correct cache_version
303
+ rename_enum_value :article_state, from: "archived", to: "deleted"
503
304
  ```
504
305
 
505
- Fixes #45341.
506
-
507
- *Austen Madden*
306
+ *Ray Faddis*
508
307
 
509
- * Fix `load_async` when called on an association proxy.
308
+ * Allow composite primary key to be derived from schema
510
309
 
511
- Calling `load_async` directly an association would schedule
512
- a query but never use it.
310
+ Booting an application with a schema that contains composite primary keys
311
+ will not issue warning and won't `nil`ify the `ActiveRecord::Base#primary_key` value anymore.
513
312
 
313
+ Given a `travel_routes` table definition and a `TravelRoute` model like:
514
314
  ```ruby
515
- comments = post.comments.load_async # schedule a query
516
- comments.to_a # perform an entirely new sync query
517
- ```
518
-
519
- Now it does use the async query, however note that it doesn't
520
- cause the association to be loaded.
521
-
522
- *Jean Boussier*
523
-
524
- * Fix eager loading for models without primary keys.
525
-
526
- *Anmol Chopra*, *Matt Lawrence*, and *Jonathan Hefner*
527
-
528
- * `rails db:schema:{dump,load}` now checks `ENV["SCHEMA_FORMAT"]` before config
529
-
530
- Since `rails db:structure:{dump,load}` was deprecated there wasn't a simple
531
- way to dump a schema to both SQL and Ruby formats. You can now do this with
532
- an environment variable. For example:
315
+ create_table :travel_routes, primary_key: [:origin, :destination], force: true do |t|
316
+ t.string :origin
317
+ t.string :destination
318
+ end
533
319
 
320
+ class TravelRoute < ActiveRecord::Base; end
534
321
  ```
535
- SCHEMA_FORMAT=sql rake db:schema:dump
536
- ```
537
-
538
- *Alex Ghiculescu*
539
-
540
- * Fix Hstore deserialize regression.
541
-
542
- *edsharp*
543
-
322
+ The `TravelRoute.primary_key` value will be automatically derived to `["origin", "destination"]`
544
323
 
545
- ## Rails 7.0.3.1 (July 12, 2022) ##
546
-
547
- * Change ActiveRecord::Coders::YAMLColumn default to safe_load
324
+ *Nikita Vasilevsky*
548
325
 
549
- This adds two new configuration options The configuration options are as
550
- follows:
326
+ * Include the `connection_pool` with exceptions raised from an adapter.
551
327
 
552
- * `config.active_record.use_yaml_unsafe_load`
328
+ The `connection_pool` provides added context such as the connection used
329
+ that led to the exception as well as which role and shard.
553
330
 
554
- When set to true, this configuration option tells Rails to use the old
555
- "unsafe" YAML loading strategy, maintaining the existing behavior but leaving
556
- the possible escalation vulnerability in place. Setting this option to true
557
- is *not* recommended, but can aid in upgrading.
331
+ *Luan Vieira*
558
332
 
559
- * `config.active_record.yaml_column_permitted_classes`
333
+ * Support multiple column ordering for `find_each`, `find_in_batches` and `in_batches`.
560
334
 
561
- The "safe YAML" loading method does not allow all classes to be deserialized
562
- by default. This option allows you to specify classes deemed "safe" in your
563
- application. For example, if your application uses Symbol and Time in
564
- serialized data, you can add Symbol and Time to the allowed list as follows:
335
+ When find_each/find_in_batches/in_batches are performed on a table with composite primary keys, ascending or descending order can be selected for each key.
565
336
 
337
+ ```ruby
338
+ Person.find_each(order: [:desc, :asc]) do |person|
339
+ person.party_all_night!
340
+ end
566
341
  ```
567
- config.active_record.yaml_column_permitted_classes = [Symbol, Date, Time]
568
- ```
569
-
570
- [CVE-2022-32224]
571
-
572
342
 
573
- ## Rails 7.0.3 (May 09, 2022) ##
574
-
575
- * Some internal housekeeping on reloads could break custom `respond_to?`
576
- methods in class objects that referenced reloadable constants. See
577
- [#44125](https://github.com/rails/rails/issues/44125) for details.
578
-
579
- *Xavier Noria*
580
-
581
- * Fixed MariaDB default function support.
343
+ *Takuya Kurimoto*
582
344
 
583
- Defaults would be written wrong in "db/schema.rb" and not work correctly
584
- if using `db:schema:load`. Further more the function name would be
585
- added as string content when saving new records.
586
-
587
- *kaspernj*
588
-
589
- * Fix `remove_foreign_key` with `:if_exists` option when foreign key actually exists.
590
-
591
- *fatkodima*
592
-
593
- * Remove `--no-comments` flag in structure dumps for PostgreSQL
594
-
595
- This broke some apps that used custom schema comments. If you don't want
596
- comments in your structure dump, you can use:
345
+ * Fix where on association with has_one/has_many polymorphic relations.
597
346
 
347
+ Before:
598
348
  ```ruby
599
- ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = ['--no-comments']
349
+ Treasure.where(price_estimates: PriceEstimate.all)
350
+ #=> SELECT (...) WHERE "treasures"."id" IN (SELECT "price_estimates"."estimate_of_id" FROM "price_estimates")
600
351
  ```
601
352
 
602
- *Alex Ghiculescu*
603
-
604
- * Use the model name as a prefix when filtering encrypted attributes from logs.
605
-
606
- For example, when encrypting `Person#name` it will add `person.name` as a filter
607
- parameter, instead of just `name`. This prevents unintended filtering of parameters
608
- with a matching name in other models.
609
-
610
- *Jorge Manrubia*
611
-
612
- * Fix quoting of `ActiveSupport::Duration` and `Rational` numbers in the MySQL adapter.
613
-
614
- *Kevin McPhillips*
615
-
616
- * Fix `change_column_comment` to preserve column's AUTO_INCREMENT in the MySQL adapter
353
+ Later:
354
+ ```ruby
355
+ Treasure.where(price_estimates: PriceEstimate.all)
356
+ #=> SELECT (...) WHERE "treasures"."id" IN (SELECT "price_estimates"."estimate_of_id" FROM "price_estimates" WHERE "price_estimates"."estimate_of_type" = 'Treasure')
357
+ ```
617
358
 
618
- *fatkodima*
359
+ *Lázaro Nixon*
619
360
 
620
- ## Rails 7.0.2.4 (April 26, 2022) ##
361
+ * Assign auto populated columns on Active Record record creation.
621
362
 
622
- * No changes.
363
+ Changes record creation logic to allow for the `auto_increment` column to be assigned
364
+ immediately after creation regardless of it's relation to the model's primary key.
623
365
 
366
+ The PostgreSQL adapter benefits the most from the change allowing for any number of auto-populated
367
+ columns to be assigned on the object immediately after row insertion utilizing the `RETURNING` statement.
624
368
 
625
- ## Rails 7.0.2.3 (March 08, 2022) ##
369
+ *Nikita Vasilevsky*
626
370
 
627
- * No changes.
371
+ * Use the first key in the `shards` hash from `connected_to` for the `default_shard`.
628
372
 
373
+ Some applications may not want to use `:default` as a shard name in their connection model. Unfortunately Active Record expects there to be a `:default` shard because it must assume a shard to get the right connection from the pool manager. Rather than force applications to manually set this, `connects_to` can infer the default shard name from the hash of shards and will now assume that the first shard is your default.
629
374
 
630
- ## Rails 7.0.2.2 (February 11, 2022) ##
375
+ For example if your model looked like this:
631
376
 
632
- * No changes.
377
+ ```ruby
378
+ class ShardRecord < ApplicationRecord
379
+ self.abstract_class = true
633
380
 
381
+ connects_to shards: {
382
+ shard_one: { writing: :shard_one },
383
+ shard_two: { writing: :shard_two }
384
+ }
385
+ ```
634
386
 
635
- ## Rails 7.0.2.1 (February 11, 2022) ##
387
+ Then the `default_shard` for this class would be set to `shard_one`.
636
388
 
637
- * No changes.
389
+ Fixes: #45390
638
390
 
391
+ *Eileen M. Uchitelle*
639
392
 
640
- ## Rails 7.0.2 (February 08, 2022) ##
393
+ * Fix mutation detection for serialized attributes backed by binary columns.
641
394
 
642
- * Fix `PG.connect` keyword arguments deprecation warning on ruby 2.7.
395
+ *Jean Boussier*
643
396
 
644
- *Nikita Vasilevsky*
397
+ * Add `ActiveRecord.disconnect_all!` method to immediately close all connections from all pools.
645
398
 
646
- * Fix the ability to exclude encryption params from being autofiltered.
399
+ *Jean Boussier*
647
400
 
648
- *Mark Gangl*
401
+ * Discard connections which may have been left in a transaction.
649
402
 
650
- * Dump the precision for datetime columns following the new defaults.
403
+ There are cases where, due to an error, `within_new_transaction` may unexpectedly leave a connection in an open transaction. In these cases the connection may be reused, and the following may occur:
404
+ - Writes appear to fail when they actually succeed.
405
+ - Writes appear to succeed when they actually fail.
406
+ - Reads return stale or uncommitted data.
651
407
 
652
- *Rafael Mendonça França*
408
+ Previously, the following case was detected:
409
+ - An error is encountered during the transaction, then another error is encountered while attempting to roll it back.
653
410
 
654
- * Make sure encrypted attributes are not being filtered twice.
411
+ Now, the following additional cases are detected:
412
+ - An error is encountered just after successfully beginning a transaction.
413
+ - An error is encountered while committing a transaction, then another error is encountered while attempting to roll it back.
414
+ - An error is encountered while rolling back a transaction.
655
415
 
656
- *Nikita Vasilevsky*
416
+ *Nick Dower*
657
417
 
658
- * Dump the database schema containing the current Rails version.
418
+ * Active Record query cache now evicts least recently used entries
659
419
 
660
- Since https://github.com/rails/rails/pull/42297, Rails now generate datetime columns
661
- with a default precision of 6. This means that users upgrading to Rails 7.0 from 6.1,
662
- when loading the database schema, would get the new precision value, which would not match
663
- the production schema.
420
+ By default it only keeps the `100` most recently used queries.
664
421
 
665
- To avoid this the schema dumper will generate the new format which will include the Rails
666
- version and will look like this:
422
+ The cache size can be configured via `database.yml`
667
423
 
668
- ```
669
- ActiveRecord::Schema[7.0].define
424
+ ```yaml
425
+ development:
426
+ adapter: mysql2
427
+ query_cache: 200
670
428
  ```
671
429
 
672
- When upgrading from Rails 6.1 to Rails 7.0, you can run the `rails app:update` task that will
673
- set the current schema version to 6.1.
430
+ It can also be entirely disabled:
674
431
 
675
- *Rafael Mendonça França*
676
-
677
- * Fix parsing expression for PostgreSQL generated column.
432
+ ```yaml
433
+ development:
434
+ adapter: mysql2
435
+ query_cache: false
436
+ ```
678
437
 
679
- *fatkodima*
438
+ *Jean Boussier*
680
439
 
681
- * Fix `Mysql2::Error: Commands out of sync; you can't run this command now`
682
- when bulk-inserting fixtures that exceed `max_allowed_packet` configuration.
440
+ * Deprecate `check_pending!` in favor of `check_all_pending!`.
683
441
 
684
- *Nikita Vasilevsky*
442
+ `check_pending!` will only check for pending migrations on the current database connection or the one passed in. This has been deprecated in favor of `check_all_pending!` which will find all pending migrations for the database configurations in a given environment.
685
443
 
686
- * Fix error when saving an association with a relation named `record`.
444
+ *Eileen M. Uchitelle*
687
445
 
688
- *Dorian Marié*
446
+ * Make `increment_counter`/`decrement_counter` accept an amount argument
689
447
 
690
- * Fix `MySQL::SchemaDumper` behavior about datetime precision value.
448
+ ```ruby
449
+ Post.increment_counter(:comments_count, 5, by: 3)
450
+ ```
691
451
 
692
- *y0t4*
452
+ *fatkodima*
693
453
 
694
- * Improve associated with no reflection error.
454
+ * Add support for `Array#intersect?` to `ActiveRecord::Relation`.
695
455
 
696
- *Nikolai*
456
+ `Array#intersect?` is only available on Ruby 3.1 or later.
697
457
 
698
- * Fix PG.connect keyword arguments deprecation warning on ruby 2.7.
458
+ This allows the Rubocop `Style/ArrayIntersect` cop to work with `ActiveRecord::Relation` objects.
699
459
 
700
- Fixes #44307.
460
+ *John Harry Kelly*
701
461
 
702
- *Nikita Vasilevsky*
462
+ * The deferrable foreign key can be passed to `t.references`.
703
463
 
704
- * Fix passing options to `check_constraint` from `change_table`.
464
+ *Hiroyuki Ishii*
705
465
 
706
- *Frederick Cheung*
466
+ * Deprecate `deferrable: true` option of `add_foreign_key`.
707
467
 
468
+ `deferrable: true` is deprecated in favor of `deferrable: :immediate`, and
469
+ will be removed in Rails 7.2.
708
470
 
709
- ## Rails 7.0.1 (January 06, 2022) ##
471
+ Because `deferrable: true` and `deferrable: :deferred` are hard to understand.
472
+ Both true and :deferred are truthy values.
473
+ This behavior is the same as the deferrable option of the add_unique_key method, added in #46192.
710
474
 
475
+ *Hiroyuki Ishii*
711
476
 
712
- * Change `QueryMethods#in_order_of` to drop records not listed in values.
477
+ * `AbstractAdapter#execute` and `#exec_query` now clear the query cache
713
478
 
714
- `in_order_of` now filters down to the values provided, to match the behavior of the `Enumerable` version.
479
+ If you need to perform a read only SQL query without clearing the query
480
+ cache, use `AbstractAdapter#select_all`.
715
481
 
716
- *Kevin Newton*
482
+ *Jean Boussier*
717
483
 
718
- * Allow named expression indexes to be revertible.
484
+ * Make `.joins` / `.left_outer_joins` work with CTEs.
719
485
 
720
- Previously, the following code would raise an error in a reversible migration executed while rolling back, due to the index name not being used in the index removal.
486
+ For example:
721
487
 
722
488
  ```ruby
723
- add_index(:settings, "(data->'property')", using: :gin, name: :index_settings_data_property)
489
+ Post
490
+ .with(commented_posts: Comment.select(:post_id).distinct)
491
+ .joins(:commented_posts)
492
+ #=> WITH (...) SELECT ... INNER JOIN commented_posts on posts.id = commented_posts.post_id
724
493
  ```
725
494
 
726
- Fixes #43331.
727
-
728
- *Oliver Günther*
729
-
730
- * Better error messages when association name is invalid in the argument of `ActiveRecord::QueryMethods::WhereChain#missing`.
731
-
732
- *ykpythemind*
733
-
734
- * Fix ordered migrations for single db in multi db environment.
735
-
736
- *Himanshu*
737
-
738
- * Extract `on update CURRENT_TIMESTAMP` for mysql2 adapter.
739
-
740
- *Kazuhiro Masuda*
741
-
742
- * Fix incorrect argument in PostgreSQL structure dump tasks.
743
-
744
- Updating the `--no-comment` argument added in Rails 7 to the correct `--no-comments` argument.
745
-
746
- *Alex Dent*
747
-
748
- * Fix schema dumping column default SQL values for sqlite3.
749
-
750
- *fatkodima*
495
+ *Vladimir Dementyev*
751
496
 
752
- * Correctly parse complex check constraint expressions for PostgreSQL.
497
+ * Add a load hook for `ActiveRecord::ConnectionAdapters::Mysql2Adapter`
498
+ (named `active_record_mysql2adapter`) to allow for overriding aspects of the
499
+ `ActiveRecord::ConnectionAdapters::Mysql2Adapter` class. This makes `Mysql2Adapter`
500
+ consistent with `PostgreSQLAdapter` and `SQLite3Adapter` that already have load hooks.
753
501
 
754
502
  *fatkodima*
755
503
 
756
- * Fix `timestamptz` attributes on PostgreSQL handle blank inputs.
757
-
758
- *Alex Ghiculescu*
759
-
760
- * Fix migration compatibility to create SQLite references/belongs_to column as integer when migration version is 6.0.
504
+ * Introduce adapter for Trilogy database client
761
505
 
762
- Reference/belongs_to in migrations with version 6.0 were creating columns as
763
- bigint instead of integer for the SQLite Adapter.
506
+ Trilogy is a MySQL-compatible database client. Rails applications can use Trilogy
507
+ by configuring their `config/database.yml`:
764
508
 
765
- *Marcelo Lauxen*
766
-
767
- * Fix joining through a polymorphic association.
768
-
769
- *Alexandre Ruban*
509
+ ```yaml
510
+ development:
511
+ adapter: trilogy
512
+ database: blog_development
513
+ pool: 5
514
+ ```
770
515
 
771
- * Fix `QueryMethods#in_order_of` to handle empty order list.
516
+ Or by using the `DATABASE_URL` environment variable:
772
517
 
773
518
  ```ruby
774
- Post.in_order_of(:id, []).to_a
519
+ ENV['DATABASE_URL'] # => "trilogy://localhost/blog_development?pool=5"
775
520
  ```
776
521
 
777
- Also more explicitly set the column as secondary order, so that any other
778
- value is still ordered.
779
-
780
- *Jean Boussier*
781
-
782
- * Fix `rails dbconsole` for 3-tier config.
783
-
784
- *Eileen M. Uchitelle*
785
-
786
- * Fix quoting of column aliases generated by calculation methods.
522
+ *Adrianna Chang*
787
523
 
788
- Since the alias is derived from the table name, we can't assume the result
789
- is a valid identifier.
524
+ * `after_commit` callbacks defined on models now execute in the correct order.
790
525
 
791
526
  ```ruby
792
- class Test < ActiveRecord::Base
793
- self.table_name = '1abc'
527
+ class User < ActiveRecord::Base
528
+ after_commit { puts("this gets called first") }
529
+ after_commit { puts("this gets called second") }
794
530
  end
795
- Test.group(:id).count
796
- # syntax error at or near "1" (ActiveRecord::StatementInvalid)
797
- # LINE 1: SELECT COUNT(*) AS count_all, "1abc"."id" AS 1abc_id FROM "1...
798
531
  ```
799
532
 
800
- *Jean Boussier*
801
-
802
-
803
- ## Rails 7.0.0 (December 15, 2021) ##
804
-
805
- * Better handle SQL queries with invalid encoding.
533
+ Previously, the callbacks executed in the reverse order. To opt in to the new behaviour:
806
534
 
807
535
  ```ruby
808
- Post.create(name: "broken \xC8 UTF-8")
536
+ config.active_record.run_after_transaction_callbacks_in_order_defined = true
809
537
  ```
810
538
 
811
- Would cause all adapters to fail in a non controlled way in the code
812
- responsible to detect write queries.
813
-
814
- The query is now properly passed to the database connection, which might or might
815
- not be able to handle it, but will either succeed or failed in a more correct way.
816
-
817
- *Jean Boussier*
818
-
819
- * Move database and shard selection config options to a generator.
820
-
821
- Rather than generating the config options in `production.rb` when applications are created, applications can now run a generator to create an initializer and uncomment / update options as needed. All multi-db configuration can be implemented in this initializer.
822
-
823
- *Eileen M. Uchitelle*
824
-
825
-
826
- ## Rails 7.0.0.rc3 (December 14, 2021) ##
827
-
828
- * No changes.
829
-
830
-
831
- ## Rails 7.0.0.rc2 (December 14, 2021) ##
539
+ This is the default for new apps.
832
540
 
833
- * No changes.
834
-
835
-
836
- ## Rails 7.0.0.rc1 (December 06, 2021) ##
837
-
838
- * Remove deprecated `ActiveRecord::DatabaseConfigurations::DatabaseConfig#spec_name`.
839
-
840
- *Rafael Mendonça França*
841
-
842
- * Remove deprecated `ActiveRecord::Connection#in_clause_length`.
843
-
844
- *Rafael Mendonça França*
845
-
846
- * Remove deprecated `ActiveRecord::Connection#allowed_index_name_length`.
847
-
848
- *Rafael Mendonça França*
849
-
850
- * Remove deprecated `ActiveRecord::Base#remove_connection`.
851
-
852
- *Rafael Mendonça França*
853
-
854
- * Load STI Models in fixtures
855
-
856
- Data from Fixtures now loads based on the specific class for models with
857
- Single Table Inheritance. This affects enums defined in subclasses, previously
858
- the value of these fields was not parsed and remained `nil`
859
-
860
- *Andres Howard*
861
-
862
- * `#authenticate` returns false when the password is blank instead of raising an error.
863
-
864
- *Muhammad Muhammad Ibrahim*
865
-
866
- * Fix `ActiveRecord::QueryMethods#in_order_of` behavior for integer enums.
867
-
868
- `ActiveRecord::QueryMethods#in_order_of` didn't work as expected for enums stored as integers in the database when passing an array of strings or symbols as the order argument. This unexpected behavior occurred because the string or symbol values were not casted to match the integers in the database.
541
+ *Alex Ghiculescu*
869
542
 
870
- The following example now works as expected:
543
+ * Infer `foreign_key` when `inverse_of` is present on `has_one` and `has_many` associations.
871
544
 
872
545
  ```ruby
873
- class Book < ApplicationRecord
874
- enum status: [:proposed, :written, :published]
875
- end
876
-
877
- Book.in_order_of(:status, %w[written published proposed])
546
+ has_many :citations, foreign_key: "book1_id", inverse_of: :book
878
547
  ```
879
548
 
880
- *Alexandre Ruban*
549
+ can be simplified to
881
550
 
882
- * Ignore persisted in-memory records when merging target lists.
883
-
884
- *Kevin Sjöberg*
551
+ ```ruby
552
+ has_many :citations, inverse_of: :book
553
+ ```
885
554
 
886
- * Add a new option `:update_only` to `upsert_all` to configure the list of columns to update in case of conflict.
555
+ and the foreign_key will be read from the corresponding `belongs_to` association.
887
556
 
888
- Before, you could only customize the update SQL sentence via `:on_duplicate`. There is now a new option `:update_only` that lets you provide a list of columns to update in case of conflict:
557
+ *Daniel Whitney*
889
558
 
890
- ```ruby
891
- Commodity.upsert_all(
892
- [
893
- { id: 2, name: "Copper", price: 4.84 },
894
- { id: 4, name: "Gold", price: 1380.87 },
895
- { id: 6, name: "Aluminium", price: 0.35 }
896
- ],
897
- update_only: [:price] # Only prices will be updated
898
- )
899
- ```
559
+ * Limit max length of auto generated index names
900
560
 
901
- *Jorge Manrubia*
561
+ Auto generated index names are now limited to 62 bytes, which fits within
562
+ the default index name length limits for MySQL, Postgres and SQLite.
902
563
 
903
- * Remove deprecated `ActiveRecord::Result#map!` and `ActiveRecord::Result#collect!`.
564
+ Any index name over the limit will fallback to the new short format.
904
565
 
905
- *Rafael Mendonça França*
566
+ Before (too long):
567
+ ```
568
+ index_testings_on_foo_and_bar_and_first_name_and_last_name_and_administrator
569
+ ```
906
570
 
907
- * Remove deprecated `ActiveRecord::Base.configurations.to_h`.
571
+ After (short format):
572
+ ```
573
+ idx_on_foo_bar_first_name_last_name_administrator_5939248142
574
+ ```
908
575
 
909
- *Rafael Mendonça França*
576
+ The short format includes a hash to ensure the name is unique database-wide.
910
577
 
911
- * Remove deprecated `ActiveRecord::Base.configurations.default_hash`.
578
+ *Mike Coutermarsh*
912
579
 
913
- *Rafael Mendonça França*
580
+ * Introduce a more stable and optimized Marshal serializer for Active Record models.
914
581
 
915
- * Remove deprecated `ActiveRecord::Base.arel_attribute`.
582
+ Can be enabled with `config.active_record.marshalling_format_version = 7.1`.
916
583
 
917
- *Rafael Mendonça França*
584
+ *Jean Boussier*
918
585
 
919
- * Remove deprecated `ActiveRecord::Base.connection_config`.
586
+ * Allow specifying where clauses with column-tuple syntax.
920
587
 
921
- *Rafael Mendonça França*
588
+ Querying through `#where` now accepts a new tuple-syntax which accepts, as
589
+ a key, an array of columns and, as a value, an array of corresponding tuples.
590
+ The key specifies a list of columns, while the value is an array of
591
+ ordered-tuples that conform to the column list.
922
592
 
923
- * Filter attributes in SQL logs
593
+ For instance:
924
594
 
925
- Previously, SQL queries in logs containing `ActiveRecord::Base.filter_attributes` were not filtered.
595
+ ```ruby
596
+ # Cpk::Book => Cpk::Book(author_id: integer, number: integer, title: string, revision: integer)
597
+ # Cpk::Book.primary_key => ["author_id", "number"]
926
598
 
927
- Now, the filter attributes will be masked `[FILTERED]` in the logs when `prepared_statement` is enabled.
599
+ book = Cpk::Book.create!(author_id: 1, number: 1)
600
+ Cpk::Book.where(Cpk::Book.primary_key => [[1, 2]]) # => [book]
928
601
 
929
- ```
930
- # Before:
931
- Foo Load (0.2ms) SELECT "foos".* FROM "foos" WHERE "foos"."passw" = ? LIMIT ? [["passw", "hello"], ["LIMIT", 1]]
602
+ # Topic => Topic(id: integer, title: string, author_name: string...)
932
603
 
933
- # After:
934
- Foo Load (0.5ms) SELECT "foos".* FROM "foos" WHERE "foos"."passw" = ? LIMIT ? [["passw", "[FILTERED]"], ["LIMIT", 1]]
604
+ Topic.where([:title, :author_name] => [["The Alchemist", "Paul Coelho"], ["Harry Potter", "J.K Rowling"]])
935
605
  ```
936
606
 
937
- *Aishwarya Subramanian*
607
+ *Paarth Madan*
938
608
 
939
- * Remove deprecated `Tasks::DatabaseTasks.spec`.
609
+ * Allow warning codes to be ignore when reporting SQL warnings.
940
610
 
941
- *Rafael Mendonça França*
611
+ Active Record config that can ignore warning codes
942
612
 
943
- * Remove deprecated `Tasks::DatabaseTasks.current_config`.
613
+ ```ruby
614
+ # Configure allowlist of warnings that should always be ignored
615
+ config.active_record.db_warnings_ignore = [
616
+ "1062", # MySQL Error 1062: Duplicate entry
617
+ ]
618
+ ```
944
619
 
945
- *Rafael Mendonça França*
620
+ This is supported for the MySQL and PostgreSQL adapters.
946
621
 
947
- * Deprecate `Tasks::DatabaseTasks.schema_file_type`.
622
+ *Nick Borromeo*
948
623
 
949
- *Rafael Mendonça França*
624
+ * Introduce `:active_record_fixtures` lazy load hook.
950
625
 
951
- * Remove deprecated `Tasks::DatabaseTasks.dump_filename`.
626
+ Hooks defined with this name will be run whenever `TestFixtures` is included
627
+ in a class.
952
628
 
953
- *Rafael Mendonça França*
629
+ ```ruby
630
+ ActiveSupport.on_load(:active_record_fixtures) do
631
+ self.fixture_paths << "test/fixtures"
632
+ end
954
633
 
955
- * Remove deprecated `Tasks::DatabaseTasks.schema_file`.
634
+ klass = Class.new
635
+ klass.include(ActiveRecord::TestFixtures)
956
636
 
957
- *Rafael Mendonça França*
637
+ klass.fixture_paths # => ["test/fixtures"]
638
+ ```
958
639
 
959
- * Remove deprecated `environment` and `name` arguments from `Tasks::DatabaseTasks.schema_up_to_date?`.
640
+ *Andrew Novoselac*
960
641
 
961
- *Rafael Mendonça França*
642
+ * Introduce `TestFixtures#fixture_paths`.
962
643
 
963
- * Merging conditions on the same column no longer maintain both conditions,
964
- and will be consistently replaced by the latter condition.
644
+ Multiple fixture paths can now be specified using the `#fixture_paths` accessor.
645
+ Apps will continue to have `test/fixtures` as their one fixture path by default,
646
+ but additional fixture paths can be specified.
965
647
 
966
648
  ```ruby
967
- # Rails 6.1 (IN clause is replaced by merger side equality condition)
968
- Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob]
969
- # Rails 6.1 (both conflict conditions exists, deprecated)
970
- Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => []
971
- # Rails 6.1 with rewhere to migrate to Rails 7.0's behavior
972
- Author.where(id: david.id..mary.id).merge(Author.where(id: bob), rewhere: true) # => [bob]
973
- # Rails 7.0 (same behavior with IN clause, mergee side condition is consistently replaced)
974
- Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob]
975
- Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => [bob]
649
+ ActiveSupport::TestCase.fixture_paths << "component1/test/fixtures"
650
+ ActiveSupport::TestCase.fixture_paths << "component2/test/fixtures"
976
651
  ```
977
652
 
978
- *Rafael Mendonça França*
979
-
980
- * Remove deprecated support to `Model.reorder(nil).first` to search using non-deterministic order.
653
+ `TestFixtures#fixture_path` is now deprecated.
981
654
 
982
- *Rafael Mendonça França*
655
+ *Andrew Novoselac*
983
656
 
984
- * Remove deprecated rake tasks:
657
+ * Adds support for deferrable exclude constraints in PostgreSQL.
985
658
 
986
- * `db:schema:load_if_ruby`
987
- * `db:structure:dump`
988
- * `db:structure:load`
989
- * `db:structure:load_if_sql`
990
- * `db:structure:dump:#{name}`
991
- * `db:structure:load:#{name}`
992
- * `db:test:load_structure`
993
- * `db:test:load_structure:#{name}`
659
+ By default, exclude constraints in PostgreSQL are checked after each statement.
660
+ This works for most use cases, but becomes a major limitation when replacing
661
+ records with overlapping ranges by using multiple statements.
994
662
 
995
- *Rafael Mendonça França*
663
+ ```ruby
664
+ exclusion_constraint :users, "daterange(valid_from, valid_to) WITH &&", deferrable: :immediate
665
+ ```
996
666
 
997
- * Remove deprecated `DatabaseConfig#config` method.
667
+ Passing `deferrable: :immediate` checks constraint after each statement,
668
+ but allows manually deferring the check using `SET CONSTRAINTS ALL DEFERRED`
669
+ within a transaction. This will cause the excludes to be checked after the transaction.
998
670
 
999
- *Rafael Mendonça França*
671
+ It's also possible to change the default behavior from an immediate check
672
+ (after the statement), to a deferred check (after the transaction):
1000
673
 
1001
- * Rollback transactions when the block returns earlier than expected.
674
+ ```ruby
675
+ exclusion_constraint :users, "daterange(valid_from, valid_to) WITH &&", deferrable: :deferred
676
+ ```
1002
677
 
1003
- Before this change, when a transaction block returned early, the transaction would be committed.
678
+ *Hiroyuki Ishii*
1004
679
 
1005
- The problem is that timeouts triggered inside the transaction block was also making the incomplete transaction
1006
- to be committed, so in order to avoid this mistake, the transaction block is rolled back.
680
+ * Respect `foreign_type` option to `delegated_type` for `{role}_class` method.
1007
681
 
1008
- *Rafael Mendonça França*
682
+ Usage of `delegated_type` with non-conventional `{role}_type` column names can now be specified with `foreign_type` option.
683
+ This option is the same as `foreign_type` as forwarded to the underlying `belongs_to` association that `delegated_type` wraps.
1009
684
 
1010
- * Add middleware for automatic shard swapping.
685
+ *Jason Karns*
1011
686
 
1012
- Provides a basic middleware to perform automatic shard swapping. Applications will provide a resolver which will determine for an individual request which shard should be used. Example:
687
+ * Add support for unique constraints (PostgreSQL-only).
1013
688
 
1014
689
  ```ruby
1015
- config.active_record.shard_resolver = ->(request) {
1016
- subdomain = request.subdomain
1017
- tenant = Tenant.find_by_subdomain!(subdomain)
1018
- tenant.shard
1019
- }
690
+ add_unique_key :sections, [:position], deferrable: :deferred, name: "unique_section_position"
691
+ remove_unique_key :sections, name: "unique_section_position"
1020
692
  ```
1021
693
 
1022
- See guides for more details.
694
+ See PostgreSQL's [Unique Constraints](https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-UNIQUE-CONSTRAINTS) documentation for more on unique constraints.
1023
695
 
1024
- *Eileen M. Uchitelle*, *John Crepezzi*
696
+ By default, unique constraints in PostgreSQL are checked after each statement.
697
+ This works for most use cases, but becomes a major limitation when replacing
698
+ records with unique column by using multiple statements.
1025
699
 
1026
- * Remove deprecated support to pass a column to `type_cast`.
1027
-
1028
- *Rafael Mendonça França*
700
+ An example of swapping unique columns between records.
1029
701
 
1030
- * Remove deprecated support to type cast to database values `ActiveRecord::Base` objects.
702
+ ```ruby
703
+ # position is unique column
704
+ old_item = Item.create!(position: 1)
705
+ new_item = Item.create!(position: 2)
1031
706
 
1032
- *Rafael Mendonça França*
707
+ Item.transaction do
708
+ old_item.update!(position: 2)
709
+ new_item.update!(position: 1)
710
+ end
711
+ ```
1033
712
 
1034
- * Remove deprecated support to quote `ActiveRecord::Base` objects.
713
+ Using the default behavior, the transaction would fail when executing the
714
+ first `UPDATE` statement.
1035
715
 
1036
- *Rafael Mendonça França*
716
+ By passing the `:deferrable` option to the `add_unique_key` statement in
717
+ migrations, it's possible to defer this check.
1037
718
 
1038
- * Remove deprecacated support to resolve connection using `"primary"` as connection specification name.
719
+ ```ruby
720
+ add_unique_key :items, [:position], deferrable: :immediate
721
+ ```
1039
722
 
1040
- *Rafael Mendonça França*
723
+ Passing `deferrable: :immediate` does not change the behaviour of the previous example,
724
+ but allows manually deferring the check using `SET CONSTRAINTS ALL DEFERRED` within a transaction.
725
+ This will cause the unique constraints to be checked after the transaction.
1041
726
 
1042
- * Remove deprecation warning when using `:interval` column is used in PostgreSQL database.
727
+ It's also possible to adjust the default behavior from an immediate
728
+ check (after the statement), to a deferred check (after the transaction):
1043
729
 
1044
- Now, interval columns will return `ActiveSupport::Duration` objects instead of strings.
730
+ ```ruby
731
+ add_unique_key :items, [:position], deferrable: :deferred
732
+ ```
1045
733
 
1046
- To keep the old behavior, you can add this line to your model:
734
+ If you want to change an existing unique index to deferrable, you can use :using_index
735
+ to create deferrable unique constraints.
1047
736
 
1048
737
  ```ruby
1049
- attribute :column, :string
738
+ add_unique_key :items, deferrable: :deferred, using_index: "index_items_on_position"
1050
739
  ```
1051
740
 
1052
- *Rafael Mendonça França*
741
+ *Hiroyuki Ishii*
1053
742
 
1054
- * Remove deprecated support to YAML load `ActiveRecord::Base` instance in the Rails 4.2 and 4.1 formats.
743
+ * Remove deprecated `Tasks::DatabaseTasks.schema_file_type`.
1055
744
 
1056
745
  *Rafael Mendonça França*
1057
746
 
1058
- * Remove deprecated option `:spec_name` in the `configs_for` method.
747
+ * Remove deprecated `config.active_record.partial_writes`.
1059
748
 
1060
749
  *Rafael Mendonça França*
1061
750
 
1062
- * Remove deprecated `ActiveRecord::Base.allow_unsafe_raw_sql`.
751
+ * Remove deprecated `ActiveRecord::Base` config accessors.
1063
752
 
1064
753
  *Rafael Mendonça França*
1065
754
 
1066
- * Fix regression bug that caused ignoring additional conditions for preloading has_many-through relations.
755
+ * Remove the `:include_replicas` argument from `configs_for`. Use `:include_hidden` argument instead.
756
+
757
+ *Eileen M. Uchitelle*
1067
758
 
1068
- Fixes #43132
759
+ * Allow applications to lookup a config via a custom hash key.
1069
760
 
1070
- *Alexander Pauly*
761
+ If you have registered a custom config or want to find configs where the hash matches a specific key, now you can pass `config_key` to `configs_for`. For example if you have a `db_config` with the key `vitess` you can look up a database configuration hash by matching that key.
1071
762
 
1072
- * Fix `has_many` inversing recursion on models with recursive associations.
763
+ ```ruby
764
+ ActiveRecord::Base.configurations.configs_for(env_name: "development", name: "primary", config_key: :vitess)
765
+ ActiveRecord::Base.configurations.configs_for(env_name: "development", config_key: :vitess)
766
+ ```
1073
767
 
1074
- *Gannon McGibbon*
768
+ *Eileen M. Uchitelle*
1075
769
 
1076
- * Add `accepts_nested_attributes_for` support for `delegated_type`
770
+ * Allow applications to register a custom database configuration handler.
1077
771
 
1078
- ```ruby
1079
- class Entry < ApplicationRecord
1080
- delegated_type :entryable, types: %w[ Message Comment ]
1081
- accepts_nested_attributes_for :entryable
1082
- end
772
+ Adds a mechanism for registering a custom handler for cases where you want database configurations to respond to custom methods. This is useful for non-Rails database adapters or tools like Vitess that you may want to configure differently from a standard `HashConfig` or `UrlConfig`.
773
+
774
+ Given the following database YAML we want the `animals` db to create a `CustomConfig` object instead while the `primary` database will be a `UrlConfig`:
775
+
776
+ ```yaml
777
+ development:
778
+ primary:
779
+ url: postgres://localhost/primary
780
+ animals:
781
+ url: postgres://localhost/animals
782
+ custom_config:
783
+ sharded: 1
784
+ ```
785
+
786
+ To register a custom handler first make a class that has your custom methods:
1083
787
 
1084
- entry = Entry.create(entryable_type: 'Message', entryable_attributes: { content: 'Hello world' })
1085
- # => #<Entry:0x00>
1086
- # id: 1
1087
- # entryable_id: 1,
1088
- # entryable_type: 'Message'
1089
- # ...>
788
+ ```ruby
789
+ class CustomConfig < ActiveRecord::DatabaseConfigurations::UrlConfig
790
+ def sharded?
791
+ custom_config.fetch("sharded", false)
792
+ end
1090
793
 
1091
- entry.entryable
1092
- # => #<Message:0x01>
1093
- # id: 1
1094
- # content: 'Hello world'
1095
- # ...>
794
+ private
795
+ def custom_config
796
+ configuration_hash.fetch(:custom_config)
797
+ end
798
+ end
1096
799
  ```
1097
800
 
1098
- Previously it would raise an error:
801
+ Then register the config in an initializer:
1099
802
 
1100
803
  ```ruby
1101
- Entry.create(entryable_type: 'Message', entryable_attributes: { content: 'Hello world' })
1102
- # ArgumentError: Cannot build association `entryable'. Are you trying to build a polymorphic one-to-one association?
804
+ ActiveRecord::DatabaseConfigurations.register_db_config_handler do |env_name, name, url, config|
805
+ next unless config.key?(:custom_config)
806
+ CustomConfig.new(env_name, name, url, config)
807
+ end
1103
808
  ```
1104
809
 
1105
- *Sjors Baltus*
810
+ When the application is booted, configuration hashes with the `:custom_config` key will be `CustomConfig` objects and respond to `sharded?`. Applications must handle the condition in which Active Record should use their custom handler.
1106
811
 
1107
- * Use subquery for DELETE with GROUP_BY and HAVING clauses.
812
+ *Eileen M. Uchitelle and John Crepezzi*
1108
813
 
1109
- Prior to this change, deletes with GROUP_BY and HAVING were returning an error.
814
+ * `ActiveRecord::Base.serialize` no longer uses YAML by default.
1110
815
 
1111
- After this change, GROUP_BY and HAVING are valid clauses in DELETE queries, generating the following query:
816
+ YAML isn't particularly performant and can lead to security issues
817
+ if not used carefully.
1112
818
 
1113
- ```sql
1114
- DELETE FROM "posts" WHERE "posts"."id" IN (
1115
- SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id" GROUP BY "posts"."id" HAVING (count(comments.id) >= 2))
1116
- ) [["flagged", "t"]]
1117
- ```
819
+ Unfortunately there isn't really any good serializers in Ruby's stdlib
820
+ to replace it.
1118
821
 
1119
- *Ignacio Chiazzo Cardarello*
822
+ The obvious choice would be JSON, which is a fine format for this use case,
823
+ however the JSON serializer in Ruby's stdlib isn't strict enough, as it fallback
824
+ to casting unknown types to strings, which could lead to corrupted data.
1120
825
 
1121
- * Use subquery for UPDATE with GROUP_BY and HAVING clauses.
826
+ Some third party JSON libraries like `Oj` have a suitable strict mode.
1122
827
 
1123
- Prior to this change, updates with GROUP_BY and HAVING were being ignored, generating a SQL like this:
828
+ So it's preferable that users choose a serializer based on their own constraints.
1124
829
 
1125
- ```sql
1126
- UPDATE "posts" SET "flagged" = ? WHERE "posts"."id" IN (
1127
- SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"
1128
- ) [["flagged", "t"]]
1129
- ```
830
+ The original default can be restored by setting `config.active_record.default_column_serializer = YAML`.
1130
831
 
1131
- After this change, GROUP_BY and HAVING clauses are used as a subquery in updates, like this:
832
+ *Jean Boussier*
1132
833
 
1133
- ```sql
1134
- UPDATE "posts" SET "flagged" = ? WHERE "posts"."id" IN (
1135
- SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"
1136
- GROUP BY posts.id HAVING (count(comments.id) >= 2)
1137
- ) [["flagged", "t"]]
1138
- ```
834
+ * `ActiveRecord::Base.serialize` signature changed.
835
+
836
+ Rather than a single positional argument that accepts two possible
837
+ types of values, `serialize` now accepts two distinct keyword arguments.
1139
838
 
1140
- *Ignacio Chiazzo Cardarello*
839
+ Before:
1141
840
 
1142
- * Add support for setting the filename of the schema or structure dump in the database config.
841
+ ```ruby
842
+ serialize :content, JSON
843
+ serialize :backtrace, Array
844
+ ```
1143
845
 
1144
- Applications may now set their the filename or path of the schema / structure dump file in their database configuration.
846
+ After:
1145
847
 
1146
- ```yaml
1147
- production:
1148
- primary:
1149
- database: my_db
1150
- schema_dump: my_schema_dump_filename.rb
1151
- animals:
1152
- database: animals_db
1153
- schema_dump: false
848
+ ```ruby
849
+ serialize :content, coder: JSON
850
+ serialize :backtrace, type: Array
1154
851
  ```
1155
852
 
1156
- The filename set in `schema_dump` will be used by the application. If set to `false` the schema will not be dumped. The database tasks are responsible for adding the database directory to the filename. If a full path is provided, the Rails tasks will use that instead of `ActiveRecord::DatabaseTasks.db_dir`.
853
+ *Jean Boussier*
1157
854
 
1158
- *Eileen M. Uchitelle*, *Ryan Kerr*
855
+ * YAML columns use `YAML.safe_dump` is available.
1159
856
 
1160
- * Add `ActiveRecord::Base.prohibit_shard_swapping` to prevent attempts to change the shard within a block.
857
+ As of `psych 5.1.0`, `YAML.safe_dump` can now apply the same permitted
858
+ types restrictions than `YAML.safe_load`.
1161
859
 
1162
- *John Crepezzi*, *Eileen M. Uchitelle*
860
+ It's preferable to ensure the payload only use allowed types when we first
861
+ try to serialize it, otherwise you may end up with invalid records in the
862
+ database.
1163
863
 
1164
- * Filter unchanged attributes with default function from insert query when `partial_inserts` is disabled.
864
+ *Jean Boussier*
1165
865
 
1166
- *Akshay Birajdar*, *Jacopo Beschi*
866
+ * `ActiveRecord::QueryLogs` better handle broken encoding.
1167
867
 
1168
- * Add support for FILTER clause (SQL:2003) to Arel.
868
+ It's not uncommon when building queries with BLOB fields to contain
869
+ binary data. Unless the call carefully encode the string in ASCII-8BIT
870
+ it generally end up being encoded in `UTF-8`, and `QueryLogs` would
871
+ end up failing on it.
1169
872
 
1170
- Currently supported by PostgreSQL 9.4+ and SQLite 3.30+.
873
+ `ActiveRecord::QueryLogs` no longer depend on the query to be properly encoded.
1171
874
 
1172
- *Andrey Novikov*
875
+ *Jean Boussier*
1173
876
 
1174
- * Automatically set timestamps on record creation during bulk insert/upsert
877
+ * Fix a bug where `ActiveRecord::Generators::ModelGenerator` would not respect create_table_migration template overrides.
1175
878
 
1176
- Prior to this change, only updates during an upsert operation (e.g. `upsert_all`) would touch timestamps (`updated_{at,on}`). Now, record creations also touch timestamp columns (`{created,updated}_{at,on}`).
879
+ ```
880
+ rails g model create_books title:string content:text
881
+ ```
882
+ will now read from the create_table_migration.rb.tt template in the following locations in order:
883
+ ```
884
+ lib/templates/active_record/model/create_table_migration.rb
885
+ lib/templates/active_record/migration/create_table_migration.rb
886
+ ```
1177
887
 
1178
- This behaviour is controlled by the `<model>.record_timestamps` config, matching the behaviour of `create`, `update`, etc. It can also be overridden by using the `record_timestamps:` keyword argument.
888
+ *Spencer Neste*
1179
889
 
1180
- Note that this means `upsert_all` on models with `record_timestamps = false` will no longer touch `updated_{at,on}` automatically.
890
+ * `ActiveRecord::Relation#explain` now accepts options.
1181
891
 
1182
- *Sam Bostock*
892
+ For databases and adapters which support them (currently PostgreSQL
893
+ and MySQL), options can be passed to `explain` to provide more
894
+ detailed query plan analysis:
1183
895
 
1184
- * Don't require `role` when passing `shard` to `connected_to`.
896
+ ```ruby
897
+ Customer.where(id: 1).joins(:orders).explain(:analyze, :verbose)
898
+ ```
1185
899
 
1186
- `connected_to` can now be called with a `shard` only. Note that `role` is still inherited if `connected_to` calls are nested.
900
+ *Reid Lynch*
1187
901
 
1188
- *Eileen M. Uchitelle*
902
+ * Multiple `Arel::Nodes::SqlLiteral` nodes can now be added together to
903
+ form `Arel::Nodes::Fragments` nodes. This allows joining several pieces
904
+ of SQL.
1189
905
 
1190
- * Add option to lazily load the schema cache on the connection.
906
+ *Matthew Draper*, *Ole Friis*
1191
907
 
1192
- Previously, the only way to load the schema cache in Active Record was through the Railtie on boot. This option provides the ability to load the schema cache on the connection after it's been established. Loading the cache lazily on the connection can be beneficial for Rails applications that use multiple databases because it will load the cache at the time the connection is established. Currently Railties doesn't have access to the connections before boot.
908
+ * `ActiveRecord::Base#signed_id` raises if called on a new record.
1193
909
 
1194
- To use the cache, set `config.active_record.lazily_load_schema_cache = true` in your application configuration. In addition a `schema_cache_path` should be set in your database configuration if you don't want to use the default "db/schema_cache.yml" path.
910
+ Previously it would return an ID that was not usable, since it was based on `id = nil`.
1195
911
 
1196
- *Eileen M. Uchitelle*
912
+ *Alex Ghiculescu*
1197
913
 
1198
- * Allow automatic `inverse_of` detection for associations with scopes.
914
+ * Allow SQL warnings to be reported.
1199
915
 
1200
- Automatic `inverse_of` detection now works for associations with scopes. For
1201
- example, the `comments` association here now automatically detects
1202
- `inverse_of: :post`, so we don't need to pass that option:
916
+ Active Record configs can be set to enable SQL warning reporting.
1203
917
 
1204
918
  ```ruby
1205
- class Post < ActiveRecord::Base
1206
- has_many :comments, -> { visible }
1207
- end
919
+ # Configure action to take when SQL query produces warning
920
+ config.active_record.db_warnings_action = :raise
1208
921
 
1209
- class Comment < ActiveRecord::Base
1210
- belongs_to :post
1211
- end
922
+ # Configure allowlist of warnings that should always be ignored
923
+ config.active_record.db_warnings_ignore = [
924
+ /Invalid utf8mb4 character string/,
925
+ "An exact warning message",
926
+ ]
1212
927
  ```
1213
928
 
1214
- Note that the automatic detection still won't work if the inverse
1215
- association has a scope. In this example a scope on the `post` association
1216
- would still prevent Rails from finding the inverse for the `comments`
1217
- association.
929
+ This is supported for the MySQL and PostgreSQL adapters.
930
+
931
+ *Adrianna Chang*, *Paarth Madan*
1218
932
 
1219
- This will be the default for new apps in Rails 7. To opt in:
933
+ * Add `#regroup` query method as a short-hand for `.unscope(:group).group(fields)`
934
+
935
+ Example:
1220
936
 
1221
937
  ```ruby
1222
- config.active_record.automatic_scope_inversing = true
938
+ Post.group(:title).regroup(:author)
939
+ # SELECT `posts`.`*` FROM `posts` GROUP BY `posts`.`author`
1223
940
  ```
1224
941
 
1225
- *Daniel Colson*, *Chris Bloom*
942
+ *Danielius Visockas*
1226
943
 
1227
- * Accept optional transaction args to `ActiveRecord::Locking::Pessimistic#with_lock`
944
+ * PostgreSQL adapter method `enable_extension` now allows parameter to be `[schema_name.]<extension_name>`
945
+ if the extension must be installed on another schema.
1228
946
 
1229
- `#with_lock` now accepts transaction options like `requires_new:`,
1230
- `isolation:`, and `joinable:`
947
+ Example: `enable_extension('heroku_ext.hstore')`
1231
948
 
1232
- *John Mileham*
949
+ *Leonardo Luarte*
1233
950
 
1234
- * Adds support for deferrable foreign key constraints in PostgreSQL.
951
+ * Add `:include` option to `add_index`.
1235
952
 
1236
- By default, foreign key constraints in PostgreSQL are checked after each statement. This works for most use cases,
1237
- but becomes a major limitation when creating related records before the parent record is inserted into the database.
1238
- One example of this is looking up / creating a person via one or more unique alias.
953
+ Add support for including non-key columns in indexes for PostgreSQL
954
+ with the `INCLUDE` parameter.
1239
955
 
1240
956
  ```ruby
1241
- Person.transaction do
1242
- alias = Alias
1243
- .create_with(user_id: SecureRandom.uuid)
1244
- .create_or_find_by(name: "DHH")
1245
-
1246
- person = Person
1247
- .create_with(name: "David Heinemeier Hansson")
1248
- .create_or_find_by(id: alias.user_id)
1249
- end
957
+ add_index(:users, :email, include: [:id, :created_at])
1250
958
  ```
1251
959
 
1252
- Using the default behavior, the transaction would fail when executing the first `INSERT` statement.
1253
-
1254
- By passing the `:deferrable` option to the `add_foreign_key` statement in migrations, it's possible to defer this
1255
- check.
960
+ will result in:
1256
961
 
1257
- ```ruby
1258
- add_foreign_key :aliases, :person, deferrable: true
962
+ ```sql
963
+ CREATE INDEX index_users_on_email USING btree (email) INCLUDE (id, created_at)
1259
964
  ```
1260
965
 
1261
- Passing `deferrable: true` doesn't change the default behavior, but allows manually deferring the check using
1262
- `SET CONSTRAINTS ALL DEFERRED` within a transaction. This will cause the foreign keys to be checked after the
1263
- transaction.
966
+ *Steve Abrams*
1264
967
 
1265
- It's also possible to adjust the default behavior from an immediate check (after the statement), to a deferred check
1266
- (after the transaction):
968
+ * `ActiveRecord::Relation`’s `#any?`, `#none?`, and `#one?` methods take an optional pattern
969
+ argument, more closely matching their `Enumerable` equivalents.
1267
970
 
1268
- ```ruby
1269
- add_foreign_key :aliases, :person, deferrable: :deferred
1270
- ```
971
+ *George Claghorn*
1271
972
 
1272
- *Benedikt Deicke*
973
+ * Add `ActiveRecord::Base.normalizes` for declaring attribute normalizations.
1273
974
 
1274
- * Allow configuring Postgres password through the socket URL.
975
+ An attribute normalization is applied when the attribute is assigned or
976
+ updated, and the normalized value will be persisted to the database. The
977
+ normalization is also applied to the corresponding keyword argument of query
978
+ methods, allowing records to be queried using unnormalized values.
1275
979
 
1276
980
  For example:
1277
- ```ruby
1278
- ActiveRecord::DatabaseConfigurations::UrlConfig.new(
1279
- :production, :production, 'postgres:///?user=user&password=secret&dbname=app', {}
1280
- ).configuration_hash
1281
- ```
1282
981
 
1283
- will now return,
982
+ ```ruby
983
+ class User < ActiveRecord::Base
984
+ normalizes :email, with: -> email { email.strip.downcase }
985
+ normalizes :phone, with: -> phone { phone.delete("^0-9").delete_prefix("1") }
986
+ end
1284
987
 
1285
- ```ruby
1286
- { :user=>"user", :password=>"secret", :dbname=>"app", :adapter=>"postgresql" }
1287
- ```
988
+ user = User.create(email: " CRUISE-CONTROL@EXAMPLE.COM\n")
989
+ user.email # => "cruise-control@example.com"
1288
990
 
1289
- *Abeid Ahmed*
991
+ user = User.find_by(email: "\tCRUISE-CONTROL@EXAMPLE.COM ")
992
+ user.email # => "cruise-control@example.com"
993
+ user.email_before_type_cast # => "cruise-control@example.com"
1290
994
 
1291
- * PostgreSQL: support custom enum types
995
+ User.where(email: "\tCRUISE-CONTROL@EXAMPLE.COM ").count # => 1
996
+ User.where(["email = ?", "\tCRUISE-CONTROL@EXAMPLE.COM "]).count # => 0
1292
997
 
1293
- In migrations, use `create_enum` to add a new enum type, and `t.enum` to add a column.
998
+ User.exists?(email: "\tCRUISE-CONTROL@EXAMPLE.COM ") # => true
999
+ User.exists?(["email = ?", "\tCRUISE-CONTROL@EXAMPLE.COM "]) # => false
1294
1000
 
1295
- ```ruby
1296
- def up
1297
- create_enum :mood, ["happy", "sad"]
1001
+ User.normalize_value_for(:phone, "+1 (555) 867-5309") # => "5558675309"
1002
+ ```
1298
1003
 
1299
- change_table :cats do |t|
1300
- t.enum :current_mood, enum_type: "mood", default: "happy", null: false
1301
- end
1302
- end
1303
- ```
1004
+ *Jonathan Hefner*
1304
1005
 
1305
- Enums will be presented correctly in `schema.rb`. Note that this is only supported by
1306
- the PostgreSQL adapter.
1006
+ * Hide changes to before_committed! callback behaviour behind flag.
1307
1007
 
1308
- *Alex Ghiculescu*
1008
+ In #46525, behavior around before_committed! callbacks was changed so that callbacks
1009
+ would run on every enrolled record in a transaction, not just the first copy of a record.
1010
+ This change in behavior is now controlled by a configuration option,
1011
+ `config.active_record.before_committed_on_all_records`. It will be enabled by default on Rails 7.1.
1309
1012
 
1310
- * Avoid COMMENT statements in PostgreSQL structure dumps
1013
+ *Adrianna Chang*
1014
+
1015
+ * The `namespaced_controller` Query Log tag now matches the `controller` format
1311
1016
 
1312
- COMMENT statements are now omitted from the output of `db:structure:dump` when using PostgreSQL >= 11.
1313
- This allows loading the dump without a pgsql superuser account.
1017
+ For example, a request processed by `NameSpaced::UsersController` will now log as:
1314
1018
 
1315
- Fixes #36816, #43107.
1019
+ ```
1020
+ :controller # "users"
1021
+ :namespaced_controller # "name_spaced/users"
1022
+ ```
1316
1023
 
1317
- *Janosch Müller*
1024
+ *Alex Ghiculescu*
1318
1025
 
1319
- * Add support for generated columns in PostgreSQL adapter
1026
+ * Return only unique ids from ActiveRecord::Calculations#ids
1320
1027
 
1321
- Generated columns are supported since version 12.0 of PostgreSQL. This adds
1322
- support of those to the PostgreSQL adapter.
1028
+ Updated ActiveRecord::Calculations#ids to only return the unique ids of the base model
1029
+ when using eager_load, preload and includes.
1323
1030
 
1324
1031
  ```ruby
1325
- create_table :users do |t|
1326
- t.string :name
1327
- t.virtual :name_upcased, type: :string, as: 'upper(name)', stored: true
1328
- end
1032
+ Post.find_by(id: 1).comments.count
1033
+ # => 5
1034
+ Post.includes(:comments).where(id: 1).pluck(:id)
1035
+ # => [1, 1, 1, 1, 1]
1036
+ Post.includes(:comments).where(id: 1).ids
1037
+ # => [1]
1329
1038
  ```
1330
1039
 
1331
- *Michał Begejowicz*
1040
+ *Joshua Young*
1332
1041
 
1042
+ * Stop using `LOWER()` for case-insensitive queries on `citext` columns
1333
1043
 
1334
- ## Rails 7.0.0.alpha2 (September 15, 2021) ##
1044
+ Previously, `LOWER()` was added for e.g. uniqueness validations with
1045
+ `case_sensitive: false`.
1046
+ It wasn't mentioned in the documentation that the index without `LOWER()`
1047
+ wouldn't be used in this case.
1335
1048
 
1336
- * No changes.
1049
+ *Phil Pirozhkov*
1337
1050
 
1051
+ * Extract `#sync_timezone_changes` method in AbstractMysqlAdapter to enable subclasses
1052
+ to sync database timezone changes without overriding `#raw_execute`.
1338
1053
 
1339
- ## Rails 7.0.0.alpha1 (September 15, 2021) ##
1054
+ *Adrianna Chang*, *Paarth Madan*
1340
1055
 
1341
- * Remove warning when overwriting existing scopes
1056
+ * Do not write additional new lines when dumping sql migration versions
1342
1057
 
1343
- Removes the following unnecessary warning message that appeared when overwriting existing scopes
1058
+ This change updates the `insert_versions_sql` function so that the database insert string containing the current database migration versions does not end with two additional new lines.
1344
1059
 
1345
- ```
1346
- Creating scope :my_scope_name. Overwriting existing method "MyClass.my_scope_name" when overwriting existing scopes
1347
- ```
1060
+ *Misha Schwartz*
1348
1061
 
1349
- *Weston Ganger*
1062
+ * Fix `composed_of` value freezing and duplication.
1350
1063
 
1351
- * Use full precision for `updated_at` in `insert_all`/`upsert_all`
1064
+ Previously composite values exhibited two confusing behaviors:
1352
1065
 
1353
- `CURRENT_TIMESTAMP` provides differing precision depending on the database,
1354
- and not all databases support explicitly specifying additional precision.
1066
+ - When reading a compositve value it'd _NOT_ be frozen, allowing it to get out of sync with its underlying database
1067
+ columns.
1068
+ - When writing a compositve value the argument would be frozen, potentially confusing the caller.
1355
1069
 
1356
- Instead, we delegate to the new `connection.high_precision_current_timestamp`
1357
- for the SQL to produce a high precision timestamp on the current database.
1070
+ Currently, composite values instantiated based on database columns are frozen (addressing the first issue) and
1071
+ assigned compositve values are duplicated and the duplicate is frozen (addressing the second issue).
1358
1072
 
1359
- Fixes #42992
1073
+ *Greg Navis*
1360
1074
 
1361
- *Sam Bostock*
1075
+ * Fix redundant updates to the column insensitivity cache
1362
1076
 
1363
- * Add ssl support for postgresql database tasks
1077
+ Fixed redundant queries checking column capability for insensitive
1078
+ comparison.
1364
1079
 
1365
- Add `PGSSLMODE`, `PGSSLCERT`, `PGSSLKEY` and `PGSSLROOTCERT` to pg_env from database config
1366
- when running postgresql database tasks.
1080
+ *Phil Pirozhkov*
1367
1081
 
1368
- ```yaml
1369
- # config/database.yml
1082
+ * Allow disabling methods generated by `ActiveRecord.enum`.
1370
1083
 
1371
- production:
1372
- sslmode: verify-full
1373
- sslcert: client.crt
1374
- sslkey: client.key
1375
- sslrootcert: ca.crt
1376
- ```
1084
+ *Alfred Dominic*
1377
1085
 
1378
- Environment variables
1086
+ * Avoid validating `belongs_to` association if it has not changed.
1379
1087
 
1380
- ```
1381
- PGSSLMODE=verify-full
1382
- PGSSLCERT=client.crt
1383
- PGSSLKEY=client.key
1384
- PGSSLROOTCERT=ca.crt
1385
- ```
1088
+ Previously, when updating a record, Active Record will perform an extra query to check for the presence of
1089
+ `belongs_to` associations (if the presence is configured to be mandatory), even if that attribute hasn't changed.
1090
+
1091
+ Currently, only `belongs_to`-related columns are checked for presence. It is possible to have orphaned records with
1092
+ this approach. To avoid this problem, you need to use a foreign key.
1093
+
1094
+ This behavior can be controlled by configuration:
1386
1095
 
1387
- Fixes #42994
1096
+ ```ruby
1097
+ config.active_record.belongs_to_required_validates_foreign_key = false
1098
+ ```
1388
1099
 
1389
- *Michael Bayucot*
1100
+ and will be disabled by default with `config.load_defaults 7.1`.
1390
1101
 
1391
- * Avoid scoping update callbacks in `ActiveRecord::Relation#update!`.
1102
+ *fatkodima*
1392
1103
 
1393
- Making it consistent with how scoping is applied only to the query in `ActiveRecord::Relation#update`
1394
- and not also to the callbacks from the update itself.
1104
+ * `has_one` and `belongs_to` associations now define a `reset_association` method
1105
+ on the owner model (where `association` is the name of the association). This
1106
+ method unloads the cached associate record, if any, and causes the next access
1107
+ to query it from the database.
1395
1108
 
1396
- *Dylan Thacker-Smith*
1109
+ *George Claghorn*
1397
1110
 
1398
- * Fix 2 cases that inferred polymorphic class from the association's `foreign_type`
1399
- using `String#constantize` instead of the model's `polymorphic_class_for`.
1111
+ * Allow per attribute setting of YAML permitted classes (safe load) and unsafe load.
1400
1112
 
1401
- When updating a polymorphic association, the old `foreign_type` was not inferred correctly when:
1402
- 1. `touch`ing the previously associated record
1403
- 2. updating the previously associated record's `counter_cache`
1113
+ *Carlos Palhares*
1404
1114
 
1405
- *Jimmy Bourassa*
1115
+ * Add a build persistence method
1406
1116
 
1407
- * Add config option for ignoring tables when dumping the schema cache.
1117
+ Provides a wrapper for `new`, to provide feature parity with `create`s
1118
+ ability to create multiple records from an array of hashes, using the
1119
+ same notation as the `build` method on associations.
1408
1120
 
1409
- Applications can now be configured to ignore certain tables when dumping the schema cache.
1121
+ *Sean Denny*
1410
1122
 
1411
- The configuration option can table an array of tables:
1123
+ * Raise on assignment to readonly attributes
1412
1124
 
1413
1125
  ```ruby
1414
- config.active_record.schema_cache_ignored_tables = ["ignored_table", "another_ignored_table"]
1126
+ class Post < ActiveRecord::Base
1127
+ attr_readonly :content
1128
+ end
1129
+ Post.create!(content: "cannot be updated")
1130
+ post.content # "cannot be updated"
1131
+ post.content = "something else" # => ActiveRecord::ReadonlyAttributeError
1415
1132
  ```
1416
1133
 
1417
- Or a regex:
1134
+ Previously, assignment would succeed but silently not write to the database.
1135
+
1136
+ This behavior can be controlled by configuration:
1418
1137
 
1419
1138
  ```ruby
1420
- config.active_record.schema_cache_ignored_tables = [/^_/]
1139
+ config.active_record.raise_on_assign_to_attr_readonly = true
1421
1140
  ```
1422
1141
 
1423
- *Eileen M. Uchitelle*
1142
+ and will be enabled by default with `config.load_defaults 7.1`.
1424
1143
 
1425
- * Make schema cache methods return consistent results.
1144
+ *Alex Ghiculescu*, *Hartley McGuire*
1426
1145
 
1427
- Previously the schema cache methods `primary_keys`, `columns`, `columns_hash`, and `indexes`
1428
- would behave differently than one another when a table didn't exist and differently across
1429
- database adapters. This change unifies the behavior so each method behaves the same regardless
1430
- of adapter.
1146
+ * Allow unscoping of preload and eager_load associations
1431
1147
 
1432
- The behavior now is:
1148
+ Added the ability to unscope preload and eager_load associations just like
1149
+ includes, joins, etc. See ActiveRecord::QueryMethods::VALID_UNSCOPING_VALUES
1150
+ for the full list of supported unscopable scopes.
1433
1151
 
1434
- `columns`: (unchanged) raises a db error if the table does not exist.
1435
- `columns_hash`: (unchanged) raises a db error if the table does not exist.
1436
- `primary_keys`: (unchanged) returns `nil` if the table does not exist.
1437
- `indexes`: (changed for mysql2) returns `[]` if the table does not exist.
1152
+ ```ruby
1153
+ query.unscope(:eager_load, :preload).group(:id).select(:id)
1154
+ ```
1438
1155
 
1439
- *Eileen M. Uchitelle*
1156
+ *David Morehouse*
1440
1157
 
1441
- * Reestablish connection to previous database after after running `db:schema:load:name`
1158
+ * Add automatic filtering of encrypted attributes on inspect
1442
1159
 
1443
- After running `db:schema:load:name` the previous connection is restored.
1160
+ This feature is enabled by default but can be disabled with
1444
1161
 
1445
- *Jacopo Beschi*
1162
+ ```ruby
1163
+ config.active_record.encryption.add_to_filter_parameters = false
1164
+ ```
1446
1165
 
1447
- * Add database config option `database_tasks`
1166
+ *Hartley McGuire*
1448
1167
 
1449
- If you would like to connect to an external database without any database
1450
- management tasks such as schema management, migrations, seeds, etc. you can set
1451
- the per database config option `database_tasks: false`
1168
+ * Clear locking column on #dup
1452
1169
 
1453
- ```yaml
1454
- # config/database.yml
1170
+ This change fixes not to duplicate locking_column like id and timestamps.
1455
1171
 
1456
- production:
1457
- primary:
1458
- database: my_database
1459
- adapter: mysql2
1460
- animals:
1461
- database: my_animals_database
1462
- adapter: mysql2
1463
- database_tasks: false
1172
+ ```
1173
+ car = Car.create!
1174
+ car.touch
1175
+ car.lock_version #=> 1
1176
+ car.dup.lock_version #=> 0
1464
1177
  ```
1465
1178
 
1466
- *Weston Ganger*
1179
+ *Shouichi Kamiya*, *Seonggi Yang*, *Ryohei UEDA*
1467
1180
 
1468
- * Fix `ActiveRecord::InternalMetadata` to not be broken by `config.active_record.record_timestamps = false`
1181
+ * Invalidate transaction as early as possible
1469
1182
 
1470
- Since the model always create the timestamp columns, it has to set them, otherwise it breaks
1471
- various DB management tasks.
1183
+ After rescuing a `TransactionRollbackError` exception Rails invalidates transactions earlier in the flow
1184
+ allowing the framework to skip issuing the `ROLLBACK` statement in more cases.
1185
+ Only affects adapters that have `savepoint_errors_invalidate_transactions?` configured as `true`,
1186
+ which at this point is only applicable to the `mysql2` adapter.
1472
1187
 
1473
- Fixes #42983
1188
+ *Nikita Vasilevsky*
1474
1189
 
1475
- * Add `ActiveRecord::QueryLogs`.
1190
+ * Allow configuring columns list to be used in SQL queries issued by an `ActiveRecord::Base` object
1476
1191
 
1477
- Configurable tags can be automatically added to all SQL queries generated by Active Record.
1192
+ It is now possible to configure columns list that will be used to build an SQL query clauses when
1193
+ updating, deleting or reloading an `ActiveRecord::Base` object
1478
1194
 
1479
1195
  ```ruby
1480
- # config/application.rb
1481
- module MyApp
1482
- class Application < Rails::Application
1483
- config.active_record.query_log_tags_enabled = true
1484
- end
1196
+ class Developer < ActiveRecord::Base
1197
+ query_constraints :company_id, :id
1485
1198
  end
1199
+ developer = Developer.first.update(name: "Bob")
1200
+ # => UPDATE "developers" SET "name" = 'Bob' WHERE "developers"."company_id" = 1 AND "developers"."id" = 1
1486
1201
  ```
1487
1202
 
1488
- By default the application, controller and action details are added to the query tags:
1203
+ *Nikita Vasilevsky*
1489
1204
 
1490
- ```ruby
1491
- class BooksController < ApplicationController
1492
- def index
1493
- @books = Book.all
1494
- end
1495
- end
1496
- ```
1205
+ * Adds `validate` to foreign keys and check constraints in schema.rb
1497
1206
 
1498
- ```ruby
1499
- GET /books
1500
- # SELECT * FROM books /*application:MyApp;controller:books;action:index*/
1501
- ```
1207
+ Previously, `schema.rb` would not record if `validate: false` had been used when adding a foreign key or check
1208
+ constraint, so restoring a database from the schema could result in foreign keys or check constraints being
1209
+ incorrectly validated.
1502
1210
 
1503
- Custom tags containing static values and Procs can be defined in the application configuration:
1211
+ *Tommy Graves*
1504
1212
 
1505
- ```ruby
1506
- config.active_record.query_log_tags = [
1507
- :application,
1508
- :controller,
1509
- :action,
1510
- {
1511
- custom_static: "foo",
1512
- custom_dynamic: -> { Time.now }
1513
- }
1514
- ]
1515
- ```
1213
+ * Adapter `#execute` methods now accept an `allow_retry` option. When set to `true`, the SQL statement will be
1214
+ retried, up to the database's configured `connection_retries` value, upon encountering connection-related errors.
1516
1215
 
1517
- *Keeran Raj Hawoldar*, *Eileen M. Uchitelle*, *Kasper Timm Hansen*
1216
+ *Adrianna Chang*
1518
1217
 
1519
- * Added support for multiple databases to `rails db:setup` and `rails db:reset`.
1218
+ * Only trigger `after_commit :destroy` callbacks when a database row is deleted.
1520
1219
 
1521
- *Ryan Hall*
1220
+ This prevents `after_commit :destroy` callbacks from being triggered again
1221
+ when `destroy` is called multiple times on the same record.
1522
1222
 
1523
- * Add `ActiveRecord::Relation#structurally_compatible?`.
1223
+ *Ben Sheldon*
1524
1224
 
1525
- Adds a query method by which a user can tell if the relation that they're
1526
- about to use for `#or` or `#and` is structurally compatible with the
1527
- receiver.
1225
+ * Fix `ciphertext_for` for yet-to-be-encrypted values.
1528
1226
 
1529
- *Kevin Newton*
1227
+ Previously, `ciphertext_for` returned the cleartext of values that had not
1228
+ yet been encrypted, such as with an unpersisted record:
1530
1229
 
1531
- * Add `ActiveRecord::QueryMethods#in_order_of`.
1230
+ ```ruby
1231
+ Post.encrypts :body
1532
1232
 
1533
- This allows you to specify an explicit order that you'd like records
1534
- returned in based on a SQL expression. By default, this will be accomplished
1535
- using a case statement, as in:
1233
+ post = Post.create!(body: "Hello")
1234
+ post.ciphertext_for(:body)
1235
+ # => "{\"p\":\"abc..."
1536
1236
 
1537
- ```ruby
1538
- Post.in_order_of(:id, [3, 5, 1])
1539
- ```
1237
+ post.body = "World"
1238
+ post.ciphertext_for(:body)
1239
+ # => "World"
1240
+ ```
1540
1241
 
1541
- will generate the SQL:
1242
+ Now, `ciphertext_for` will always return the ciphertext of encrypted
1243
+ attributes:
1542
1244
 
1543
- ```sql
1544
- SELECT "posts".* FROM "posts" ORDER BY CASE "posts"."id" WHEN 3 THEN 1 WHEN 5 THEN 2 WHEN 1 THEN 3 ELSE 4 END ASC
1545
- ```
1245
+ ```ruby
1246
+ Post.encrypts :body
1546
1247
 
1547
- However, because this functionality is built into MySQL in the form of the
1548
- `FIELD` function, that connection adapter will generate the following SQL
1549
- instead:
1248
+ post = Post.create!(body: "Hello")
1249
+ post.ciphertext_for(:body)
1250
+ # => "{\"p\":\"abc..."
1550
1251
 
1551
- ```sql
1552
- SELECT "posts".* FROM "posts" ORDER BY FIELD("posts"."id", 1, 5, 3) DESC
1553
- ```
1252
+ post.body = "World"
1253
+ post.ciphertext_for(:body)
1254
+ # => "{\"p\":\"xyz..."
1255
+ ```
1554
1256
 
1555
- *Kevin Newton*
1257
+ *Jonathan Hefner*
1556
1258
 
1557
- * Fix `eager_loading?` when ordering with `Symbol`.
1259
+ * Fix a bug where using groups and counts with long table names would return incorrect results.
1558
1260
 
1559
- `eager_loading?` is triggered correctly when using `order` with symbols.
1261
+ *Shota Toguchi*, *Yusaku Ono*
1560
1262
 
1561
- ```ruby
1562
- scope = Post.includes(:comments).order(:"comments.label")
1563
- => true
1564
- ```
1263
+ * Fix encryption of column default values.
1565
1264
 
1566
- *Jacopo Beschi*
1265
+ Previously, encrypted attributes that used column default values appeared to
1266
+ be encrypted on create, but were not:
1567
1267
 
1568
- * Two change tracking methods are added for `belongs_to` associations.
1268
+ ```ruby
1269
+ Book.encrypts :name
1569
1270
 
1570
- The `association_changed?` method (assuming an association named `:association`) returns true
1571
- if a different associated object has been assigned and the foreign key will be updated in the
1572
- next save.
1271
+ book = Book.create!
1272
+ book.name
1273
+ # => "<untitled>"
1274
+ book.name_before_type_cast
1275
+ # => "{\"p\":\"abc..."
1276
+ book.reload.name_before_type_cast
1277
+ # => "<untitled>"
1278
+ ```
1573
1279
 
1574
- The `association_previously_changed?` method returns true if the previous save updated the
1575
- association to reference a different associated object.
1280
+ Now, attributes with column default values are encrypted:
1576
1281
 
1577
- *George Claghorn*
1282
+ ```ruby
1283
+ Book.encrypts :name
1578
1284
 
1579
- * Add option to disable schema dump per-database.
1285
+ book = Book.create!
1286
+ book.name
1287
+ # => "<untitled>"
1288
+ book.name_before_type_cast
1289
+ # => "{\"p\":\"abc..."
1290
+ book.reload.name_before_type_cast
1291
+ # => "{\"p\":\"abc..."
1292
+ ```
1580
1293
 
1581
- Dumping the schema is on by default for all databases in an application. To turn it off for a
1582
- specific database, use the `schema_dump` option:
1294
+ *Jonathan Hefner*
1583
1295
 
1584
- ```yaml
1585
- # config/database.yml
1296
+ * Deprecate delegation from `Base` to `connection_handler`.
1586
1297
 
1587
- production:
1588
- schema_dump: false
1589
- ```
1298
+ Calling `Base.clear_all_connections!`, `Base.clear_active_connections!`, `Base.clear_reloadable_connections!` and `Base.flush_idle_connections!` is deprecated. Please call these methods on the connection handler directly. In future Rails versions, the delegation from `Base` to the `connection_handler` will be removed.
1590
1299
 
1591
- *Luis Vasconcellos*, *Eileen M. Uchitelle*
1300
+ *Eileen M. Uchitelle*
1592
1301
 
1593
- * Fix `eager_loading?` when ordering with `Hash` syntax.
1302
+ * Allow ActiveRecord::QueryMethods#reselect to receive hash values, similar to ActiveRecord::QueryMethods#select
1594
1303
 
1595
- `eager_loading?` is triggered correctly when using `order` with hash syntax
1596
- on an outer table.
1304
+ *Sampat Badhe*
1597
1305
 
1598
- ```ruby
1599
- Post.includes(:comments).order({ "comments.label": :ASC }).eager_loading?
1600
- # => true
1601
- ```
1306
+ * Validate options when managing columns and tables in migrations.
1602
1307
 
1603
- *Jacopo Beschi*
1308
+ If an invalid option is passed to a migration method like `create_table` and `add_column`, an error will be raised
1309
+ instead of the option being silently ignored. Validation of the options will only be applied for new migrations
1310
+ that are created.
1604
1311
 
1605
- * Move the forcing of clear text encoding to the `ActiveRecord::Encryption::Encryptor`.
1312
+ *Guo Xiang Tan*, *George Wambold*
1606
1313
 
1607
- Fixes #42699.
1314
+ * Update query log tags to use the [SQLCommenter](https://open-telemetry.github.io/opentelemetry-sqlcommenter/) format by default. See [#46179](https://github.com/rails/rails/issues/46179)
1608
1315
 
1609
- *J Smith*
1316
+ To opt out of SQLCommenter-formatted query log tags, set `config.active_record.query_log_tags_format = :legacy`. By default, this is set to `:sqlcommenter`.
1610
1317
 
1611
- * `partial_inserts` is now disabled by default in new apps.
1318
+ *Modulitos* and *Iheanyi*
1612
1319
 
1613
- This will be the default for new apps in Rails 7. To opt in:
1320
+ * Allow any ERB in the database.yml when creating rake tasks.
1614
1321
 
1615
- ```ruby
1616
- config.active_record.partial_inserts = true
1617
- ```
1322
+ Any ERB can be used in `database.yml` even if it accesses environment
1323
+ configurations.
1618
1324
 
1619
- If a migration removes the default value of a column, this option
1620
- would cause old processes to no longer be able to create new records.
1325
+ Deprecates `config.active_record.suppress_multiple_database_warning`.
1621
1326
 
1622
- If you need to remove a column, you should first use `ignored_columns`
1623
- to stop using it.
1327
+ *Eike Send*
1624
1328
 
1625
- *Jean Boussier*
1329
+ * Add table to error for duplicate column definitions.
1626
1330
 
1627
- * Rails can now verify foreign keys after loading fixtures in tests.
1331
+ If a migration defines duplicate columns for a table, the error message
1332
+ shows which table it concerns.
1628
1333
 
1629
- This will be the default for new apps in Rails 7. To opt in:
1334
+ *Petrik de Heus*
1630
1335
 
1631
- ```ruby
1632
- config.active_record.verify_foreign_keys_for_fixtures = true
1633
- ```
1336
+ * Fix erroneous nil default precision on virtual datetime columns.
1634
1337
 
1635
- Tests will not run if there is a foreign key constraint violation in your fixture data.
1338
+ Prior to this change, virtual datetime columns did not have the same
1339
+ default precision as regular datetime columns, resulting in the following
1340
+ being erroneously equivalent:
1636
1341
 
1637
- The feature is supported by SQLite and PostgreSQL, other adapters can also add support for it.
1342
+ t.virtual :name, type: datetime, as: "expression"
1343
+ t.virtual :name, type: datetime, precision: nil, as: "expression"
1638
1344
 
1639
- *Alex Ghiculescu*
1345
+ This change fixes the default precision lookup, so virtual and regular
1346
+ datetime column default precisions match.
1640
1347
 
1641
- * Clear cached `has_one` association after setting `belongs_to` association to `nil`.
1348
+ *Sam Bostock*
1642
1349
 
1643
- After setting a `belongs_to` relation to `nil` and updating an unrelated attribute on the owner,
1644
- the owner should still return `nil` on the `has_one` relation.
1350
+ * Use connection from `#with_raw_connection` in `#quote_string`.
1645
1351
 
1646
- Fixes #42597.
1352
+ This ensures that the string quoting is wrapped in the reconnect and retry logic
1353
+ that `#with_raw_connection` offers.
1647
1354
 
1648
- *Michiel de Mare*
1355
+ *Adrianna Chang*
1649
1356
 
1650
- * OpenSSL constants are now used for Digest computations.
1357
+ * Add `expires_in` option to `signed_id`.
1651
1358
 
1652
- *Dirkjan Bussink*
1359
+ *Shouichi Kamiya*
1653
1360
 
1654
- * Adds support for `if_not_exists` to `add_foreign_key` and `if_exists` to `remove_foreign_key`.
1361
+ * Allow applications to set retry deadline for query retries.
1655
1362
 
1656
- Applications can set their migrations to ignore exceptions raised when adding a foreign key
1657
- that already exists or when removing a foreign key that does not exist.
1363
+ Building on the work done in #44576 and #44591, we extend the logic that automatically
1364
+ reconnects database connections to take into account a timeout limit. We won't retry
1365
+ a query if a given amount of time has elapsed since the query was first attempted. This
1366
+ value defaults to nil, meaning that all retryable queries are retried regardless of time elapsed,
1367
+ but this can be changed via the `retry_deadline` option in the database config.
1658
1368
 
1659
- Example Usage:
1369
+ *Adrianna Chang*
1660
1370
 
1661
- ```ruby
1662
- class AddAuthorsForeignKeyToArticles < ActiveRecord::Migration[7.0]
1663
- def change
1664
- add_foreign_key :articles, :authors, if_not_exists: true
1665
- end
1666
- end
1371
+ * Fix a case where the query cache can return wrong values. See #46044
1372
+
1373
+ *Aaron Patterson*
1374
+
1375
+ * Support MySQL's ssl-mode option for MySQLDatabaseTasks.
1376
+
1377
+ Verifying the identity of the database server requires setting the ssl-mode
1378
+ option to VERIFY_CA or VERIFY_IDENTITY. This option was previously ignored
1379
+ for MySQL database tasks like creating a database and dumping the structure.
1380
+
1381
+ *Petrik de Heus*
1382
+
1383
+ * Move `ActiveRecord::InternalMetadata` to an independent object.
1384
+
1385
+ `ActiveRecord::InternalMetadata` no longer inherits from `ActiveRecord::Base` and is now an independent object that should be instantiated with a `connection`. This class is private and should not be used by applications directly. If you want to interact with the schema migrations table, please access it on the connection directly, for example: `ActiveRecord::Base.connection.schema_migration`.
1386
+
1387
+ *Eileen M. Uchitelle*
1388
+
1389
+ * Deprecate quoting `ActiveSupport::Duration` as an integer
1390
+
1391
+ Using ActiveSupport::Duration as an interpolated bind parameter in a SQL
1392
+ string template is deprecated. To avoid this warning, you should explicitly
1393
+ convert the duration to a more specific database type. For example, if you
1394
+ want to use a duration as an integer number of seconds:
1667
1395
  ```
1396
+ Record.where("duration = ?", 1.hour.to_i)
1397
+ ```
1398
+ If you want to use a duration as an ISO 8601 string:
1399
+ ```
1400
+ Record.where("duration = ?", 1.hour.iso8601)
1401
+ ```
1402
+
1403
+ *Aram Greenman*
1404
+
1405
+ * Allow `QueryMethods#in_order_of` to order by a string column name.
1668
1406
 
1669
1407
  ```ruby
1670
- class RemoveAuthorsForeignKeyFromArticles < ActiveRecord::Migration[7.0]
1671
- def change
1672
- remove_foreign_key :articles, :authors, if_exists: true
1673
- end
1674
- end
1408
+ Post.in_order_of("id", [4,2,3,1]).to_a
1409
+ Post.joins(:author).in_order_of("authors.name", ["Bob", "Anna", "John"]).to_a
1675
1410
  ```
1676
1411
 
1677
- *Roberto Miranda*
1412
+ *Igor Kasyanchuk*
1413
+
1414
+ * Move `ActiveRecord::SchemaMigration` to an independent object.
1415
+
1416
+ `ActiveRecord::SchemaMigration` no longer inherits from `ActiveRecord::Base` and is now an independent object that should be instantiated with a `connection`. This class is private and should not be used by applications directly. If you want to interact with the schema migrations table, please access it on the connection directly, for example: `ActiveRecord::Base.connection.schema_migration`.
1417
+
1418
+ *Eileen M. Uchitelle*
1419
+
1420
+ * Deprecate `all_connection_pools` and make `connection_pool_list` more explicit.
1678
1421
 
1679
- * Prevent polluting ENV during postgresql structure dump/load.
1422
+ Following on #45924 `all_connection_pools` is now deprecated. `connection_pool_list` will either take an explicit role or applications can opt into the new behavior by passing `:all`.
1680
1423
 
1681
- Some configuration parameters were provided to pg_dump / psql via
1682
- environment variables which persisted beyond the command being run, and may
1683
- have caused subsequent commands and connections to fail. Tasks running
1684
- across multiple postgresql databases like `rails db:test:prepare` may have
1685
- been affected.
1424
+ *Eileen M. Uchitelle*
1425
+
1426
+ * Fix connection handler methods to operate on all pools.
1427
+
1428
+ `active_connections?`, `clear_active_connections!`, `clear_reloadable_connections!`, `clear_all_connections!`, and `flush_idle_connections!` now operate on all pools by default. Previously they would default to using the `current_role` or `:writing` role unless specified.
1429
+
1430
+ *Eileen M. Uchitelle*
1431
+
1432
+
1433
+ * Allow ActiveRecord::QueryMethods#select to receive hash values.
1434
+
1435
+ Currently, `select` might receive only raw sql and symbols to define columns and aliases to select.
1686
1436
 
1687
- *Samuel Cochran*
1437
+ With this change we can provide `hash` as argument, for example:
1688
1438
 
1689
- * Set precision 6 by default for `datetime` columns.
1439
+ ```ruby
1440
+ Post.joins(:comments).select(posts: [:id, :title, :created_at], comments: [:id, :body, :author_id])
1441
+ #=> "SELECT \"posts\".\"id\", \"posts\".\"title\", \"posts\".\"created_at\", \"comments\".\"id\", \"comments\".\"body\", \"comments\".\"author_id\"
1442
+ # FROM \"posts\" INNER JOIN \"comments\" ON \"comments\".\"post_id\" = \"posts\".\"id\""
1690
1443
 
1691
- By default, datetime columns will have microseconds precision instead of seconds precision.
1444
+ Post.joins(:comments).select(posts: { id: :post_id, title: :post_title }, comments: { id: :comment_id, body: :comment_body })
1445
+ #=> "SELECT posts.id as post_id, posts.title as post_title, comments.id as comment_id, comments.body as comment_body
1446
+ # FROM \"posts\" INNER JOIN \"comments\" ON \"comments\".\"post_id\" = \"posts\".\"id\""
1447
+ ```
1448
+ *Oleksandr Holubenko*, *Josef Šimánek*, *Jean Boussier*
1692
1449
 
1693
- *Roberto Miranda*
1450
+ * Adapts virtual attributes on `ActiveRecord::Persistence#becomes`.
1694
1451
 
1695
- * Allow preloading of associations with instance dependent scopes.
1452
+ When source and target classes have a different set of attributes adapts
1453
+ attributes such that the extra attributes from target are added.
1696
1454
 
1697
- *John Hawthorn*, *John Crepezzi*, *Adam Hess*, *Eileen M. Uchitelle*, *Dinah Shi*
1455
+ ```ruby
1456
+ class Person < ApplicationRecord
1457
+ end
1698
1458
 
1699
- * Do not try to rollback transactions that failed due to a `ActiveRecord::TransactionRollbackError`.
1459
+ class WebUser < Person
1460
+ attribute :is_admin, :boolean
1461
+ after_initialize :set_admin
1700
1462
 
1701
- *Jamie McCarthy*
1463
+ def set_admin
1464
+ write_attribute(:is_admin, email =~ /@ourcompany\.com$/)
1465
+ end
1466
+ end
1702
1467
 
1703
- * Active Record Encryption will now encode values as UTF-8 when using deterministic
1704
- encryption. The encoding is part of the encrypted payload, so different encodings for
1705
- different values result in different ciphertexts. This can break unique constraints and
1706
- queries.
1468
+ person = Person.find_by(email: "email@ourcompany.com")
1469
+ person.respond_to? :is_admin
1470
+ # => false
1471
+ person.becomes(WebUser).is_admin?
1472
+ # => true
1473
+ ```
1707
1474
 
1708
- The new behavior is configurable via `active_record.encryption.forced_encoding_for_deterministic_encryption`
1709
- that is `Encoding::UTF_8` by default. It can be disabled by setting it to `nil`.
1475
+ *Jacopo Beschi*, *Sampson Crowley*
1710
1476
 
1711
- *Jorge Manrubia*
1477
+ * Fix `ActiveRecord::QueryMethods#in_order_of` to include `nil`s, to match the
1478
+ behavior of `Enumerable#in_order_of`.
1712
1479
 
1713
- * The MySQL adapter now cast numbers and booleans bind parameters to string for safety reasons.
1480
+ For example, `Post.in_order_of(:title, [nil, "foo"])` will now include posts
1481
+ with `nil` titles, the same as `Post.all.to_a.in_order_of(:title, [nil, "foo"])`.
1714
1482
 
1715
- When comparing a string and a number in a query, MySQL converts the string to a number. So for
1716
- instance `"foo" = 0`, will implicitly cast `"foo"` to `0` and will evaluate to `TRUE` which can
1717
- lead to security vulnerabilities.
1483
+ *fatkodima*
1718
1484
 
1719
- Active Record already protect against that vulnerability when it knows the type of the column
1720
- being compared, however until now it was still vulnerable when using bind parameters:
1485
+ * Optimize `add_timestamps` to use a single SQL statement.
1721
1486
 
1722
1487
  ```ruby
1723
- User.where("login_token = ?", 0).first
1488
+ add_timestamps :my_table
1724
1489
  ```
1725
1490
 
1726
- Would perform:
1491
+ Now results in the following SQL:
1727
1492
 
1728
1493
  ```sql
1729
- SELECT * FROM `users` WHERE `login_token` = 0 LIMIT 1;
1494
+ ALTER TABLE "my_table" ADD COLUMN "created_at" datetime(6) NOT NULL, ADD COLUMN "updated_at" datetime(6) NOT NULL
1730
1495
  ```
1731
1496
 
1732
- Now it will perform:
1733
-
1734
- ```sql
1735
- SELECT * FROM `users` WHERE `login_token` = '0' LIMIT 1;
1736
- ```
1497
+ *Iliana Hadzhiatanasova*
1737
1498
 
1738
- *Jean Boussier*
1499
+ * Add `drop_enum` migration command for PostgreSQL
1739
1500
 
1740
- * Fixture configurations (`_fixture`) are now strictly validated.
1501
+ This does the inverse of `create_enum`. Before dropping an enum, ensure you have
1502
+ dropped columns that depend on it.
1741
1503
 
1742
- If an error will be raised if that entry contains unknown keys while previously it
1743
- would silently have no effects.
1504
+ *Alex Ghiculescu*
1744
1505
 
1745
- *Jean Boussier*
1506
+ * Adds support for `if_exists` option when removing a check constraint.
1746
1507
 
1747
- * Add `ActiveRecord::Base.update!` that works like `ActiveRecord::Base.update` but raises exceptions.
1508
+ The `remove_check_constraint` method now accepts an `if_exists` option. If set
1509
+ to true an error won't be raised if the check constraint doesn't exist.
1748
1510
 
1749
- This allows for the same behavior as the instance method `#update!` at a class level.
1511
+ *Margaret Parsa* and *Aditya Bhutani*
1750
1512
 
1751
- ```ruby
1752
- Person.update!(:all, state: "confirmed")
1753
- ```
1513
+ * `find_or_create_by` now try to find a second time if it hits a unicity constraint.
1754
1514
 
1755
- *Dorian Marié*
1515
+ `find_or_create_by` always has been inherently racy, either creating multiple
1516
+ duplicate records or failing with `ActiveRecord::RecordNotUnique` depending on
1517
+ whether a proper unicity constraint was set.
1756
1518
 
1757
- * Add `ActiveRecord::Base#attributes_for_database`.
1519
+ `create_or_find_by` was introduced for this use case, however it's quite wasteful
1520
+ when the record is expected to exist most of the time, as INSERT require to send
1521
+ more data than SELECT and require more work from the database. Also on some
1522
+ databases it can actually consume a primary key increment which is undesirable.
1758
1523
 
1759
- Returns attributes with values for assignment to the database.
1524
+ So for case where most of the time the record is expected to exist, `find_or_create_by`
1525
+ can be made race-condition free by re-trying the `find` if the `create` failed
1526
+ with `ActiveRecord::RecordNotUnique`. This assumes that the table has the proper
1527
+ unicity constraints, if not, `find_or_create_by` will still lead to duplicated records.
1760
1528
 
1761
- *Chris Salzberg*
1529
+ *Jean Boussier*, *Alex Kitchens*
1762
1530
 
1763
- * Use an empty query to check if the PostgreSQL connection is still active.
1531
+ * Introduce a simpler constructor API for ActiveRecord database adapters.
1764
1532
 
1765
- An empty query is faster than `SELECT 1`.
1533
+ Previously the adapter had to know how to build a new raw connection to
1534
+ support reconnect, but also expected to be passed an initial already-
1535
+ established connection.
1766
1536
 
1767
- *Heinrich Lee Yu*
1537
+ When manually creating an adapter instance, it will now accept a single
1538
+ config hash, and only establish the real connection on demand.
1768
1539
 
1769
- * Add `ActiveRecord::Base#previously_persisted?`.
1540
+ *Matthew Draper*
1770
1541
 
1771
- Returns `true` if the object has been previously persisted but now it has been deleted.
1542
+ * Avoid redundant `SELECT 1` connection-validation query during DB pool
1543
+ checkout when possible.
1772
1544
 
1773
- * Deprecate `partial_writes` in favor of `partial_inserts` and `partial_updates`.
1545
+ If the first query run during a request is known to be idempotent, it can be
1546
+ used directly to validate the connection, saving a network round-trip.
1774
1547
 
1775
- This allows to have a different behavior on update and create.
1548
+ *Matthew Draper*
1776
1549
 
1777
- *Jean Boussier*
1550
+ * Automatically reconnect broken database connections when safe, even
1551
+ mid-request.
1778
1552
 
1779
- * Fix compatibility with `psych >= 4`.
1553
+ When an error occurs while attempting to run a known-idempotent query, and
1554
+ not inside a transaction, it is safe to immediately reconnect to the
1555
+ database server and try again, so this is now the default behavior.
1780
1556
 
1781
- Starting in Psych 4.0.0 `YAML.load` behaves like `YAML.safe_load`. To preserve compatibility,
1782
- Active Record's schema cache loader and `YAMLColumn` now uses `YAML.unsafe_load` if available.
1557
+ This new default should always be safe -- to support that, it's consciously
1558
+ conservative about which queries are considered idempotent -- but if
1559
+ necessary it can be disabled by setting the `connection_retries` connection
1560
+ option to `0`.
1783
1561
 
1784
- *Jean Boussier*
1562
+ *Matthew Draper*
1785
1563
 
1786
- * `ActiveRecord::Base.logger` is now a `class_attribute`.
1564
+ * Avoid removing a PostgreSQL extension when there are dependent objects.
1787
1565
 
1788
- This means it can no longer be accessed directly through `@@logger`, and that setting `logger =`
1789
- on a subclass won't change the parent's logger.
1566
+ Previously, removing an extension also implicitly removed dependent objects. Now, this will raise an error.
1790
1567
 
1791
- *Jean Boussier*
1568
+ You can force removing the extension:
1792
1569
 
1793
- * Add `.asc.nulls_first` for all databases. Unfortunately MySQL still doesn't like `nulls_last`.
1570
+ ```ruby
1571
+ disable_extension :citext, force: :cascade
1572
+ ```
1794
1573
 
1795
- *Keenan Brock*
1574
+ Fixes #29091.
1796
1575
 
1797
- * Improve performance of `one?` and `many?` by limiting the generated count query to 2 results.
1576
+ *fatkodima*
1798
1577
 
1799
- *Gonzalo Riestra*
1578
+ * Allow nested functions as safe SQL string
1800
1579
 
1801
- * Don't check type when using `if_not_exists` on `add_column`.
1580
+ *Michael Siegfried*
1802
1581
 
1803
- Previously, if a migration called `add_column` with the `if_not_exists` option set to true
1804
- the `column_exists?` check would look for a column with the same name and type as the migration.
1582
+ * Allow `destroy_association_async_job=` to be configured with a class string instead of a constant.
1805
1583
 
1806
- Recently it was discovered that the type passed to the migration is not always the same type
1807
- as the column after migration. For example a column set to `:mediumblob` in the migration will
1808
- be casted to `binary` when calling `column.type`. Since there is no straightforward way to cast
1809
- the type to the database type without running the migration, we opted to drop the type check from
1810
- `add_column`. This means that migrations adding a duplicate column with a different type will no
1811
- longer raise an error.
1584
+ Defers an autoloading dependency between `ActiveRecord::Base` and `ActiveJob::Base`
1585
+ and moves the configuration of `ActiveRecord::DestroyAssociationAsyncJob`
1586
+ from ActiveJob to ActiveRecord.
1812
1587
 
1813
- *Eileen M. Uchitelle*
1588
+ Deprecates `ActiveRecord::ActiveJobRequiredError` and now raises a `NameError`
1589
+ if the job class is unloadable or an `ActiveRecord::ConfigurationError` if
1590
+ `dependent: :destroy_async` is declared on an association but there is no job
1591
+ class configured.
1814
1592
 
1815
- * Log a warning message when running SQLite in production.
1593
+ *Ben Sheldon*
1816
1594
 
1817
- Using SQLite in production ENV is generally discouraged. SQLite is also the default adapter
1818
- in a new Rails application.
1819
- For the above reasons log a warning message when running SQLite in production.
1595
+ * Fix `ActiveRecord::Store` to serialize as a regular Hash
1820
1596
 
1821
- The warning can be disabled by setting `config.active_record.sqlite3_production_warning=false`.
1597
+ Previously it would serialize as an `ActiveSupport::HashWithIndifferentAccess`
1598
+ which is wasteful and cause problem with YAML safe_load.
1822
1599
 
1823
- *Jacopo Beschi*
1600
+ *Jean Boussier*
1824
1601
 
1825
- * Add option to disable joins for `has_one` associations.
1602
+ * Add `timestamptz` as a time zone aware type for PostgreSQL
1826
1603
 
1827
- In a multiple database application, associations can't join across
1828
- databases. When set, this option instructs Rails to generate 2 or
1829
- more queries rather than generating joins for `has_one` associations.
1604
+ This is required for correctly parsing `timestamp with time zone` values in your database.
1830
1605
 
1831
- Set the option on a has one through association:
1606
+ If you don't want this, you can opt out by adding this initializer:
1832
1607
 
1833
1608
  ```ruby
1834
- class Person
1835
- has_one :dog
1836
- has_one :veterinarian, through: :dog, disable_joins: true
1837
- end
1838
- ```
1839
-
1840
- Then instead of generating join SQL, two queries are used for `@person.veterinarian`:
1841
-
1842
- ```
1843
- SELECT "dogs"."id" FROM "dogs" WHERE "dogs"."person_id" = ? [["person_id", 1]]
1844
- SELECT "veterinarians".* FROM "veterinarians" WHERE "veterinarians"."dog_id" = ? [["dog_id", 1]]
1609
+ ActiveRecord::Base.time_zone_aware_types -= [:timestamptz]
1845
1610
  ```
1846
1611
 
1847
- *Sarah Vessels*, *Eileen M. Uchitelle*
1848
-
1849
- * `Arel::Visitors::Dot` now renders a complete set of properties when visiting
1850
- `Arel::Nodes::SelectCore`, `SelectStatement`, `InsertStatement`, `UpdateStatement`, and
1851
- `DeleteStatement`, which fixes #42026. Previously, some properties were omitted.
1852
-
1853
- *Mike Dalessio*
1612
+ *Alex Ghiculescu*
1854
1613
 
1855
- * `Arel::Visitors::Dot` now supports `Arel::Nodes::Bin`, `Case`, `CurrentRow`, `Distinct`,
1856
- `DistinctOn`, `Else`, `Except`, `InfixOperation`, `Intersect`, `Lock`, `NotRegexp`, `Quoted`,
1857
- `Regexp`, `UnaryOperation`, `Union`, `UnionAll`, `When`, and `With`. Previously, these node
1858
- types caused an exception to be raised by `Arel::Visitors::Dot#accept`.
1614
+ * Add new `ActiveRecord::Base.generates_token_for` API.
1859
1615
 
1860
- *Mike Dalessio*
1616
+ Currently, `signed_id` fulfills the role of generating tokens for e.g.
1617
+ resetting a password. However, signed IDs cannot reflect record state, so
1618
+ if a token is intended to be single-use, it must be tracked in a database at
1619
+ least until it expires.
1861
1620
 
1862
- * Optimize `remove_columns` to use a single SQL statement.
1621
+ With `generates_token_for`, a token can embed data from a record. When
1622
+ using the token to fetch the record, the data from the token and the current
1623
+ data from the record will be compared. If the two do not match, the token
1624
+ will be treated as invalid, the same as if it had expired. For example:
1863
1625
 
1864
1626
  ```ruby
1865
- remove_columns :my_table, :col_one, :col_two
1866
- ```
1627
+ class User < ActiveRecord::Base
1628
+ has_secure_password
1867
1629
 
1868
- Now results in the following SQL:
1630
+ generates_token_for :password_reset, expires_in: 15.minutes do
1631
+ # A password's BCrypt salt changes when the password is updated.
1632
+ # By embedding (part of) the salt in a token, the token will
1633
+ # expire when the password is updated.
1634
+ BCrypt::Password.new(password_digest).salt[-10..]
1635
+ end
1636
+ end
1869
1637
 
1870
- ```sql
1871
- ALTER TABLE "my_table" DROP COLUMN "col_one", DROP COLUMN "col_two"
1872
- ```
1638
+ user = User.first
1639
+ token = user.generate_token_for(:password_reset)
1873
1640
 
1874
- *Jon Dufresne*
1641
+ User.find_by_token_for(:password_reset, token) # => user
1875
1642
 
1876
- * Ensure `has_one` autosave association callbacks get called once.
1643
+ user.update!(password: "new password")
1644
+ User.find_by_token_for(:password_reset, token) # => nil
1645
+ ```
1877
1646
 
1878
- Change the `has_one` autosave callback to be non cyclic as well.
1879
- By doing this the autosave callback are made more consistent for
1880
- all 3 cases: `has_many`, `has_one`, and `belongs_to`.
1647
+ *Jonathan Hefner*
1881
1648
 
1882
- *Petrik de Heus*
1649
+ * Optimize Active Record batching for whole table iterations.
1883
1650
 
1884
- * Add option to disable joins for associations.
1651
+ Previously, `in_batches` got all the ids and constructed an `IN`-based query for each batch.
1652
+ When iterating over the whole tables, this approach is not optimal as it loads unneeded ids and
1653
+ `IN` queries with lots of items are slow.
1885
1654
 
1886
- In a multiple database application, associations can't join across
1887
- databases. When set, this option instructs Rails to generate 2 or
1888
- more queries rather than generating joins for associations.
1655
+ Now, whole table iterations use range iteration (`id >= x AND id <= y`) by default which can make iteration
1656
+ several times faster. E.g., tested on a PostgreSQL table with 10 million records: querying (`253s` vs `30s`),
1657
+ updating (`288s` vs `124s`), deleting (`268s` vs `83s`).
1889
1658
 
1890
- Set the option on a has many through association:
1659
+ Only whole table iterations use this style of iteration by default. You can disable this behavior by passing `use_ranges: false`.
1660
+ If you iterate over the table and the only condition is, e.g., `archived_at: nil` (and only a tiny fraction
1661
+ of the records are archived), it makes sense to opt in to this approach:
1891
1662
 
1892
1663
  ```ruby
1893
- class Dog
1894
- has_many :treats, through: :humans, disable_joins: true
1895
- has_many :humans
1664
+ Project.where(archived_at: nil).in_batches(use_ranges: true) do |relation|
1665
+ # do something
1896
1666
  end
1897
1667
  ```
1898
1668
 
1899
- Then instead of generating join SQL, two queries are used for `@dog.treats`:
1900
-
1901
- ```
1902
- SELECT "humans"."id" FROM "humans" WHERE "humans"."dog_id" = ? [["dog_id", 1]]
1903
- SELECT "treats".* FROM "treats" WHERE "treats"."human_id" IN (?, ?, ?) [["human_id", 1], ["human_id", 2], ["human_id", 3]]
1904
- ```
1905
-
1906
- *Eileen M. Uchitelle*, *Aaron Patterson*, *Lee Quarella*
1907
-
1908
- * Add setting for enumerating column names in SELECT statements.
1669
+ See #45414 for more details.
1909
1670
 
1910
- Adding a column to a PostgreSQL database, for example, while the application is running can
1911
- change the result of wildcard `SELECT *` queries, which invalidates the result
1912
- of cached prepared statements and raises a `PreparedStatementCacheExpired` error.
1913
-
1914
- When enabled, Active Record will avoid wildcards and always include column names
1915
- in `SELECT` queries, which will return consistent results and avoid prepared
1916
- statement errors.
1671
+ *fatkodima*
1917
1672
 
1918
- Before:
1673
+ * `.with` query method added. Construct common table expressions with ease and get `ActiveRecord::Relation` back.
1919
1674
 
1920
1675
  ```ruby
1921
- Book.limit(5)
1922
- # SELECT * FROM books LIMIT 5
1676
+ Post.with(posts_with_comments: Post.where("comments_count > ?", 0))
1677
+ # => ActiveRecord::Relation
1678
+ # WITH posts_with_comments AS (SELECT * FROM posts WHERE (comments_count > 0)) SELECT * FROM posts
1923
1679
  ```
1924
1680
 
1925
- After:
1926
-
1927
- ```ruby
1928
- # config/application.rb
1929
- module MyApp
1930
- class Application < Rails::Application
1931
- config.active_record.enumerate_columns_in_select_statements = true
1932
- end
1933
- end
1681
+ *Vlado Cingel*
1934
1682
 
1935
- # or, configure per-model
1936
- class Book < ApplicationRecord
1937
- self.enumerate_columns_in_select_statements = true
1938
- end
1939
- ```
1683
+ * Don't establish a new connection if an identical pool exists already.
1940
1684
 
1941
- ```ruby
1942
- Book.limit(5)
1943
- # SELECT id, author_id, name, format, status, language, etc FROM books LIMIT 5
1944
- ```
1685
+ Previously, if `establish_connection` was called on a class that already had an established connection, the existing connection would be removed regardless of whether it was the same config. Now if a pool is found with the same values as the new connection, the existing connection will be returned instead of creating a new one.
1945
1686
 
1946
- *Matt Duszynski*
1687
+ This has a slight change in behavior if application code is depending on a new connection being established regardless of whether it's identical to an existing connection. If the old behavior is desirable, applications should call `ActiveRecord::Base#remove_connection` before establishing a new one. Calling `establish_connection` with a different config works the same way as it did previously.
1947
1688
 
1948
- * Allow passing SQL as `on_duplicate` value to `#upsert_all` to make it possible to use raw SQL to update columns on conflict:
1689
+ *Eileen M. Uchitelle*
1949
1690
 
1950
- ```ruby
1951
- Book.upsert_all(
1952
- [{ id: 1, status: 1 }, { id: 2, status: 1 }],
1953
- on_duplicate: Arel.sql("status = GREATEST(books.status, EXCLUDED.status)")
1954
- )
1955
- ```
1691
+ * Update `db:prepare` task to load schema when an uninitialized database exists, and dump schema after migrations.
1956
1692
 
1957
- *Vladimir Dementyev*
1693
+ *Ben Sheldon*
1958
1694
 
1959
- * Allow passing SQL as `returning` statement to `#upsert_all`:
1695
+ * Fix supporting timezone awareness for `tsrange` and `tstzrange` array columns.
1960
1696
 
1961
1697
  ```ruby
1962
- Article.insert_all(
1963
- [
1964
- { title: "Article 1", slug: "article-1", published: false },
1965
- { title: "Article 2", slug: "article-2", published: false }
1966
- ],
1967
- returning: Arel.sql("id, (xmax = '0') as inserted, name as new_name")
1968
- )
1698
+ # In database migrations
1699
+ add_column :shops, :open_hours, :tsrange, array: true
1700
+ # In app config
1701
+ ActiveRecord::Base.time_zone_aware_types += [:tsrange]
1702
+ # In the code times are properly converted to app time zone
1703
+ Shop.create!(open_hours: [Time.current..8.hour.from_now])
1969
1704
  ```
1970
1705
 
1971
- *Vladimir Dementyev*
1706
+ *Wojciech Wnętrzak*
1972
1707
 
1973
- * Deprecate `legacy_connection_handling`.
1708
+ * Introduce strategy pattern for executing migrations.
1974
1709
 
1975
- *Eileen M. Uchitelle*
1710
+ By default, migrations will use a strategy object that delegates the method
1711
+ to the connection adapter. Consumers can implement custom strategy objects
1712
+ to change how their migrations run.
1976
1713
 
1977
- * Add attribute encryption support.
1714
+ *Adrianna Chang*
1978
1715
 
1979
- Encrypted attributes are declared at the model level. These
1980
- are regular Active Record attributes backed by a column with
1981
- the same name. The system will transparently encrypt these
1982
- attributes before saving them into the database and will
1983
- decrypt them when retrieving their values.
1716
+ * Add adapter option disallowing foreign keys
1984
1717
 
1718
+ This adds a new option to be added to `database.yml` which enables skipping
1719
+ foreign key constraints usage even if the underlying database supports them.
1985
1720
 
1986
- ```ruby
1987
- class Person < ApplicationRecord
1988
- encrypts :name
1989
- encrypts :email_address, deterministic: true
1990
- end
1721
+ Usage:
1722
+ ```yaml
1723
+ development:
1724
+ <<: *default
1725
+ database: storage/development.sqlite3
1726
+ foreign_keys: false
1991
1727
  ```
1992
1728
 
1993
- You can learn more in the [Active Record Encryption
1994
- guide](https://edgeguides.rubyonrails.org/active_record_encryption.html).
1729
+ *Paulo Barros*
1995
1730
 
1996
- *Jorge Manrubia*
1731
+ * Add configurable deprecation warning for singular associations
1997
1732
 
1998
- * Changed Arel predications `contains` and `overlaps` to use
1999
- `quoted_node` so that PostgreSQL arrays are quoted properly.
1733
+ This adds a deprecation warning when using the plural name of a singular associations in `where`.
1734
+ It is possible to opt into the new more performant behavior with `config.active_record.allow_deprecated_singular_associations_name = false`
2000
1735
 
2001
- *Bradley Priest*
1736
+ *Adam Hess*
2002
1737
 
2003
- * Add mode argument to record level `strict_loading!`.
1738
+ * Run transactional callbacks on the freshest instance to save a given
1739
+ record within a transaction.
2004
1740
 
2005
- This argument can be used when enabling strict loading for a single record
2006
- to specify that we only want to raise on n plus one queries.
1741
+ When multiple Active Record instances change the same record within a
1742
+ transaction, Rails runs `after_commit` or `after_rollback` callbacks for
1743
+ only one of them. `config.active_record.run_commit_callbacks_on_first_saved_instances_in_transaction`
1744
+ was added to specify how Rails chooses which instance receives the
1745
+ callbacks. The framework defaults were changed to use the new logic.
2007
1746
 
2008
- ```ruby
2009
- developer.strict_loading!(mode: :n_plus_one_only)
1747
+ When `config.active_record.run_commit_callbacks_on_first_saved_instances_in_transaction`
1748
+ is `true`, transactional callbacks are run on the first instance to save,
1749
+ even though its instance state may be stale.
2010
1750
 
2011
- developer.projects.to_a # Does not raise
2012
- developer.projects.first.client # Raises StrictLoadingViolationError
2013
- ```
1751
+ When it is `false`, which is the new framework default starting with version
1752
+ 7.1, transactional callbacks are run on the instances with the freshest
1753
+ instance state. Those instances are chosen as follows:
2014
1754
 
2015
- Previously, enabling strict loading would cause any lazily loaded
2016
- association to raise an error. Using `n_plus_one_only` mode allows us to
2017
- lazily load belongs_to, has_many, and other associations that are fetched
2018
- through a single query.
1755
+ - In general, run transactional callbacks on the last instance to save a
1756
+ given record within the transaction.
1757
+ - There are two exceptions:
1758
+ - If the record is created within the transaction, then updated by
1759
+ another instance, `after_create_commit` callbacks will be run on the
1760
+ second instance. This is instead of the `after_update_commit`
1761
+ callbacks that would naively be run based on that instance’s state.
1762
+ - If the record is destroyed within the transaction, then
1763
+ `after_destroy_commit` callbacks will be fired on the last destroyed
1764
+ instance, even if a stale instance subsequently performed an update
1765
+ (which will have affected 0 rows).
2019
1766
 
2020
- *Dinah Shi*
1767
+ *Cameron Bothner and Mitch Vollebregt*
2021
1768
 
2022
- * Fix Float::INFINITY assignment to datetime column with postgresql adapter.
1769
+ * Enable strict strings mode for `SQLite3Adapter`.
2023
1770
 
2024
- Before:
1771
+ Configures SQLite with a strict strings mode, which disables double-quoted string literals.
2025
1772
 
2026
- ```ruby
2027
- # With this config
2028
- ActiveRecord::Base.time_zone_aware_attributes = true
1773
+ SQLite has some quirks around double-quoted string literals.
1774
+ It first tries to consider double-quoted strings as identifier names, but if they don't exist
1775
+ it then considers them as string literals. Because of this, typos can silently go unnoticed.
1776
+ For example, it is possible to create an index for a non existing column.
1777
+ See [SQLite documentation](https://www.sqlite.org/quirks.html#double_quoted_string_literals_are_accepted) for more details.
2029
1778
 
2030
- # and the following schema:
2031
- create_table "postgresql_infinities" do |t|
2032
- t.datetime "datetime"
2033
- end
1779
+ If you don't want this behavior, you can disable it via:
2034
1780
 
2035
- # This test fails
2036
- record = PostgresqlInfinity.create!(datetime: Float::INFINITY)
2037
- assert_equal Float::INFINITY, record.datetime # record.datetime gets nil
1781
+ ```ruby
1782
+ # config/application.rb
1783
+ config.active_record.sqlite3_adapter_strict_strings_by_default = false
2038
1784
  ```
2039
1785
 
2040
- After this commit, `record.datetime` gets `Float::INFINITY` as expected.
1786
+ Fixes #27782.
1787
+
1788
+ *fatkodima*, *Jean Boussier*
2041
1789
 
2042
- *Shunichi Ikegami*
1790
+ * Resolve issue where a relation cache_version could be left stale.
2043
1791
 
2044
- * Type cast enum values by the original attribute type.
1792
+ Previously, when `reset` was called on a relation object it did not reset the cache_versions
1793
+ ivar. This led to a confusing situation where despite having the correct data the relation
1794
+ still reported a stale cache_version.
2045
1795
 
2046
- The notable thing about this change is that unknown labels will no longer match 0 on MySQL.
1796
+ Usage:
2047
1797
 
2048
1798
  ```ruby
2049
- class Book < ActiveRecord::Base
2050
- enum :status, { proposed: 0, written: 1, published: 2 }
2051
- end
2052
- ```
1799
+ developers = Developer.all
1800
+ developers.cache_version
2053
1801
 
2054
- Before:
1802
+ Developer.update_all(updated_at: Time.now.utc + 1.second)
2055
1803
 
2056
- ```ruby
2057
- # SELECT `books`.* FROM `books` WHERE `books`.`status` = 'prohibited' LIMIT 1
2058
- Book.find_by(status: :prohibited)
2059
- # => #<Book id: 1, status: "proposed", ...> (for mysql2 adapter)
2060
- # => ActiveRecord::StatementInvalid: PG::InvalidTextRepresentation: ERROR: invalid input syntax for type integer: "prohibited" (for postgresql adapter)
2061
- # => nil (for sqlite3 adapter)
1804
+ developers.cache_version # Stale cache_version
1805
+ developers.reset
1806
+ developers.cache_version # Returns the current correct cache_version
2062
1807
  ```
2063
1808
 
2064
- After:
1809
+ Fixes #45341.
1810
+
1811
+ *Austen Madden*
1812
+
1813
+ * Add support for exclusion constraints (PostgreSQL-only).
2065
1814
 
2066
1815
  ```ruby
2067
- # SELECT `books`.* FROM `books` WHERE `books`.`status` IS NULL LIMIT 1
2068
- Book.find_by(status: :prohibited)
2069
- # => nil (for all adapters)
1816
+ add_exclusion_constraint :invoices, "daterange(start_date, end_date) WITH &&", using: :gist, name: "invoices_date_overlap"
1817
+ remove_exclusion_constraint :invoices, name: "invoices_date_overlap"
2070
1818
  ```
2071
1819
 
2072
- *Ryuta Kamizono*
1820
+ See PostgreSQL's [`CREATE TABLE ... EXCLUDE ...`](https://www.postgresql.org/docs/12/sql-createtable.html#SQL-CREATETABLE-EXCLUDE) documentation for more on exclusion constraints.
2073
1821
 
2074
- * Fixtures for `has_many :through` associations now load timestamps on join tables.
1822
+ *Alex Robbin*
2075
1823
 
2076
- Given this fixture:
1824
+ * `change_column_null` raises if a non-boolean argument is provided
2077
1825
 
2078
- ```yml
2079
- ### monkeys.yml
2080
- george:
2081
- name: George the Monkey
2082
- fruits: apple
1826
+ Previously if you provided a non-boolean argument, `change_column_null` would
1827
+ treat it as truthy and make your column nullable. This could be surprising, so now
1828
+ the input must be either `true` or `false`.
2083
1829
 
2084
- ### fruits.yml
2085
- apple:
2086
- name: apple
1830
+ ```ruby
1831
+ change_column_null :table, :column, true # good
1832
+ change_column_null :table, :column, false # good
1833
+ change_column_null :table, :column, from: true, to: false # raises (previously this made the column nullable)
2087
1834
  ```
2088
1835
 
2089
- If the join table (`fruit_monkeys`) contains `created_at` or `updated_at` columns,
2090
- these will now be populated when loading the fixture. Previously, fixture loading
2091
- would crash if these columns were required, and leave them as null otherwise.
2092
-
2093
1836
  *Alex Ghiculescu*
2094
1837
 
2095
- * Allow applications to configure the thread pool for async queries.
1838
+ * Enforce limit on table names length.
2096
1839
 
2097
- Some applications may want one thread pool per database whereas others want to use
2098
- a single global thread pool for all queries. By default, Rails will set `async_query_executor`
2099
- to `nil` which will not initialize any executor. If `load_async` is called and no executor
2100
- has been configured, the query will be executed in the foreground.
1840
+ Fixes #45130.
2101
1841
 
2102
- To create one thread pool for all database connections to use applications can set
2103
- `config.active_record.async_query_executor` to `:global_thread_pool` and optionally define
2104
- `config.active_record.global_executor_concurrency`. This defaults to 4. For applications that want
2105
- to have a thread pool for each database connection, `config.active_record.async_query_executor` can
2106
- be set to `:multi_thread_pool`. The configuration for each thread pool is set in the database
2107
- configuration.
1842
+ *fatkodima*
2108
1843
 
2109
- *Eileen M. Uchitelle*
1844
+ * Adjust the minimum MariaDB version for check constraints support.
2110
1845
 
2111
- * Allow new syntax for `enum` to avoid leading `_` from reserved options.
1846
+ *Eddie Lebow*
2112
1847
 
2113
- Before:
1848
+ * Fix Hstore deserialize regression.
2114
1849
 
2115
- ```ruby
2116
- class Book < ActiveRecord::Base
2117
- enum status: [ :proposed, :written ], _prefix: true, _scopes: false
2118
- enum cover: [ :hard, :soft ], _suffix: true, _default: :hard
2119
- end
2120
- ```
1850
+ *edsharp*
2121
1851
 
2122
- After:
1852
+ * Add validity for PostgreSQL indexes.
2123
1853
 
2124
1854
  ```ruby
2125
- class Book < ActiveRecord::Base
2126
- enum :status, [ :proposed, :written ], prefix: true, scopes: false
2127
- enum :cover, [ :hard, :soft ], suffix: true, default: :hard
2128
- end
1855
+ connection.index_exists?(:users, :email, valid: true)
1856
+ connection.indexes(:users).select(&:valid?)
2129
1857
  ```
2130
1858
 
2131
- *Ryuta Kamizono*
1859
+ *fatkodima*
2132
1860
 
2133
- * Add `ActiveRecord::Relation#load_async`.
1861
+ * Fix eager loading for models without primary keys.
2134
1862
 
2135
- This method schedules the query to be performed asynchronously from a thread pool.
1863
+ *Anmol Chopra*, *Matt Lawrence*, and *Jonathan Hefner*
2136
1864
 
2137
- If the result is accessed before a background thread had the opportunity to perform
2138
- the query, it will be performed in the foreground.
1865
+ * Avoid validating a unique field if it has not changed and is backed by a unique index.
2139
1866
 
2140
- This is useful for queries that can be performed long enough before their result will be
2141
- needed, or for controllers which need to perform several independent queries.
1867
+ Previously, when saving a record, Active Record will perform an extra query to check for the
1868
+ uniqueness of each attribute having a `uniqueness` validation, even if that attribute hasn't changed.
1869
+ If the database has the corresponding unique index, then this validation can never fail for persisted
1870
+ records, and we could safely skip it.
2142
1871
 
2143
- ```ruby
2144
- def index
2145
- @categories = Category.some_complex_scope.load_async
2146
- @posts = Post.some_complex_scope.load_async
2147
- end
2148
- ```
1872
+ *fatkodima*
2149
1873
 
2150
- Active Record logs will also include timing info for the duration of how long
2151
- the main thread had to wait to access the result. This timing is useful to know
2152
- whether or not it's worth to load the query asynchronously.
1874
+ * Stop setting `sql_auto_is_null`
2153
1875
 
2154
- ```
2155
- DEBUG -- : Category Load (62.1ms) SELECT * FROM `categories` LIMIT 50
2156
- DEBUG -- : ASYNC Post Load (64ms) (db time 126.1ms) SELECT * FROM `posts` LIMIT 100
2157
- ```
1876
+ Since version 5.5 the default has been off, we no longer have to manually turn it off.
2158
1877
 
2159
- The duration in the first set of parens is how long the main thread was blocked
2160
- waiting for the results, and the second set of parens with "db time" is how long
2161
- the entire query took to execute.
1878
+ *Adam Hess*
2162
1879
 
2163
- *Jean Boussier*
1880
+ * Fix `touch` to raise an error for readonly columns.
2164
1881
 
2165
- * Implemented `ActiveRecord::Relation#excluding` method.
1882
+ *fatkodima*
2166
1883
 
2167
- This method excludes the specified record (or collection of records) from
2168
- the resulting relation:
1884
+ * Add ability to ignore tables by regexp for SQL schema dumps.
2169
1885
 
2170
1886
  ```ruby
2171
- Post.excluding(post)
2172
- Post.excluding(post_one, post_two)
1887
+ ActiveRecord::SchemaDumper.ignore_tables = [/^_/]
2173
1888
  ```
2174
1889
 
2175
- Also works on associations:
2176
-
2177
- ```ruby
2178
- post.comments.excluding(comment)
2179
- post.comments.excluding(comment_one, comment_two)
2180
- ```
1890
+ *fatkodima*
2181
1891
 
2182
- This is short-hand for `Post.where.not(id: post.id)` (for a single record)
2183
- and `Post.where.not(id: [post_one.id, post_two.id])` (for a collection).
1892
+ * Avoid queries when performing calculations on contradictory relations.
2184
1893
 
2185
- *Glen Crawford*
1894
+ Previously calculations would make a query even when passed a
1895
+ contradiction, such as `User.where(id: []).count`. We no longer perform a
1896
+ query in that scenario.
2186
1897
 
2187
- * Skip optimised #exist? query when #include? is called on a relation
2188
- with a having clause.
1898
+ This applies to the following calculations: `count`, `sum`, `average`,
1899
+ `minimum` and `maximum`
2189
1900
 
2190
- Relations that have aliased select values AND a having clause that
2191
- references an aliased select value would generate an error when
2192
- #include? was called, due to an optimisation that would generate
2193
- call #exists? on the relation instead, which effectively alters
2194
- the select values of the query (and thus removes the aliased select
2195
- values), but leaves the having clause intact. Because the having
2196
- clause is then referencing an aliased column that is no longer
2197
- present in the simplified query, an ActiveRecord::InvalidStatement
2198
- error was raised.
1901
+ *Luan Vieira, John Hawthorn and Daniel Colson*
2199
1902
 
2200
- A sample query affected by this problem:
1903
+ * Allow using aliased attributes with `insert_all`/`upsert_all`.
2201
1904
 
2202
1905
  ```ruby
2203
- Author.select('COUNT(*) as total_posts', 'authors.*')
2204
- .joins(:posts)
2205
- .group(:id)
2206
- .having('total_posts > 2')
2207
- .include?(Author.first)
1906
+ class Book < ApplicationRecord
1907
+ alias_attribute :title, :name
1908
+ end
1909
+
1910
+ Book.insert_all [{ title: "Remote", author_id: 1 }], returning: :title
2208
1911
  ```
2209
1912
 
2210
- This change adds an addition check to the condition that skips the
2211
- simplified #exists? query, which simply checks for the presence of
2212
- a having clause.
1913
+ *fatkodima*
2213
1914
 
2214
- Fixes #41417.
1915
+ * Support encrypted attributes on columns with default db values.
2215
1916
 
2216
- *Michael Smart*
1917
+ This adds support for encrypted attributes defined on columns with default values.
1918
+ It will encrypt those values at creation time. Before, it would raise an
1919
+ error unless `config.active_record.encryption.support_unencrypted_data` was true.
2217
1920
 
2218
- * Increment postgres prepared statement counter before making a prepared statement, so if the statement is aborted
2219
- without Rails knowledge (e.g., if app gets killed during long-running query or due to Rack::Timeout), app won't end
2220
- up in perpetual crash state for being inconsistent with PostgreSQL.
1921
+ *Jorge Manrubia* and *Dima Fatko*
2221
1922
 
2222
- *wbharding*, *Martin Tepper*
1923
+ * Allow overriding `reading_request?` in `DatabaseSelector::Resolver`
2223
1924
 
2224
- * Add ability to apply `scoping` to `all_queries`.
1925
+ The default implementation checks if a request is a `get?` or `head?`,
1926
+ but you can now change it to anything you like. If the method returns true,
1927
+ `Resolver#read` gets called meaning the request could be served by the
1928
+ replica database.
2225
1929
 
2226
- Some applications may want to use the `scoping` method but previously it only
2227
- worked on certain types of queries. This change allows the `scoping` method to apply
2228
- to all queries for a model in a block.
1930
+ *Alex Ghiculescu*
2229
1931
 
2230
- ```ruby
2231
- Post.where(blog_id: post.blog_id).scoping(all_queries: true) do
2232
- post.update(title: "a post title") # adds `posts.blog_id = 1` to the query
2233
- end
2234
- ```
1932
+ * Remove `ActiveRecord.legacy_connection_handling`.
2235
1933
 
2236
1934
  *Eileen M. Uchitelle*
2237
1935
 
2238
- * `ActiveRecord::Calculations.calculate` called with `:average`
2239
- (aliased as `ActiveRecord::Calculations.average`) will now use column-based
2240
- type casting. This means that floating-point number columns will now be
2241
- aggregated as `Float` and decimal columns will be aggregated as `BigDecimal`.
1936
+ * `rails db:schema:{dump,load}` now checks `ENV["SCHEMA_FORMAT"]` before config
2242
1937
 
2243
- Integers are handled as a special case returning `BigDecimal` always
2244
- (this was the case before already).
1938
+ Since `rails db:structure:{dump,load}` was deprecated there wasn't a simple
1939
+ way to dump a schema to both SQL and Ruby formats. You can now do this with
1940
+ an environment variable. For example:
2245
1941
 
2246
- ```ruby
2247
- # With the following schema:
2248
- create_table "measurements" do |t|
2249
- t.float "temperature"
2250
- end
1942
+ ```
1943
+ SCHEMA_FORMAT=sql rake db:schema:dump
1944
+ ```
2251
1945
 
2252
- # Before:
2253
- Measurement.average(:temperature).class
2254
- # => BigDecimal
1946
+ *Alex Ghiculescu*
2255
1947
 
2256
- # After:
2257
- Measurement.average(:temperature).class
2258
- # => Float
2259
- ```
1948
+ * Fixed MariaDB default function support.
1949
+
1950
+ Defaults would be written wrong in "db/schema.rb" and not work correctly
1951
+ if using `db:schema:load`. Further more the function name would be
1952
+ added as string content when saving new records.
2260
1953
 
2261
- Before this change, Rails just called `to_d` on average aggregates from the
2262
- database adapter. This is not the case anymore. If you relied on that kind
2263
- of magic, you now need to register your own `ActiveRecord::Type`
2264
- (see `ActiveRecord::Attributes::ClassMethods` for documentation).
1954
+ *kaspernj*
2265
1955
 
2266
- *Josua Schmid*
1956
+ * Add `active_record.destroy_association_async_batch_size` configuration
2267
1957
 
2268
- * PostgreSQL: introduce `ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.datetime_type`.
1958
+ This allows applications to specify the maximum number of records that will
1959
+ be destroyed in a single background job by the `dependent: :destroy_async`
1960
+ association option. By default, the current behavior will remain the same:
1961
+ when a parent record is destroyed, all dependent records will be destroyed
1962
+ in a single background job. If the number of dependent records is greater
1963
+ than this configuration, the records will be destroyed in multiple
1964
+ background jobs.
2269
1965
 
2270
- This setting controls what native type Active Record should use when you call `datetime` in
2271
- a migration or schema. It takes a symbol which must correspond to one of the configured
2272
- `NATIVE_DATABASE_TYPES`. The default is `:timestamp`, meaning `t.datetime` in a migration
2273
- will create a "timestamp without time zone" column. To use "timestamp with time zone",
2274
- change this to `:timestamptz` in an initializer.
1966
+ *Nick Holden*
2275
1967
 
2276
- You should run `bin/rails db:migrate` to rebuild your schema.rb if you change this.
1968
+ * Fix `remove_foreign_key` with `:if_exists` option when foreign key actually exists.
2277
1969
 
2278
- *Alex Ghiculescu*
1970
+ *fatkodima*
1971
+
1972
+ * Remove `--no-comments` flag in structure dumps for PostgreSQL
2279
1973
 
2280
- * PostgreSQL: handle `timestamp with time zone` columns correctly in `schema.rb`.
1974
+ This broke some apps that used custom schema comments. If you don't want
1975
+ comments in your structure dump, you can use:
2281
1976
 
2282
- Previously they dumped as `t.datetime :column_name`, now they dump as `t.timestamptz :column_name`,
2283
- and are created as `timestamptz` columns when the schema is loaded.
1977
+ ```ruby
1978
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = ['--no-comments']
1979
+ ```
2284
1980
 
2285
1981
  *Alex Ghiculescu*
2286
1982
 
2287
- * Removing trailing whitespace when matching columns in
2288
- `ActiveRecord::Sanitization.disallow_raw_sql!`.
1983
+ * Reduce the memory footprint of fixtures accessors.
2289
1984
 
2290
- *Gannon McGibbon*, *Adrian Hirt*
1985
+ Until now fixtures accessors were eagerly defined using `define_method`.
1986
+ So the memory usage was directly dependent of the number of fixtures and
1987
+ test suites.
2291
1988
 
2292
- * Expose a way for applications to set a `primary_abstract_class`.
1989
+ Instead fixtures accessors are now implemented with `method_missing`,
1990
+ so they incur much less memory and CPU overhead.
2293
1991
 
2294
- Multiple database applications that use a primary abstract class that is not
2295
- named `ApplicationRecord` can now set a specific class to be the `primary_abstract_class`.
1992
+ *Jean Boussier*
2296
1993
 
2297
- ```ruby
2298
- class PrimaryApplicationRecord
2299
- self.primary_abstract_class
2300
- end
2301
- ```
1994
+ * Fix `config.active_record.destroy_association_async_job` configuration
2302
1995
 
2303
- When an application boots it automatically connects to the primary or first database in the
2304
- database configuration file. In a multiple database application that then call `connects_to`
2305
- needs to know that the default connection is the same as the `ApplicationRecord` connection.
2306
- However, some applications have a differently named `ApplicationRecord`. This prevents Active
2307
- Record from opening duplicate connections to the same database.
1996
+ `config.active_record.destroy_association_async_job` should allow
1997
+ applications to specify the job that will be used to destroy associated
1998
+ records in the background for `has_many` associations with the
1999
+ `dependent: :destroy_async` option. Previously, that was ignored, which
2000
+ meant the default `ActiveRecord::DestroyAssociationAsyncJob` always
2001
+ destroyed records in the background.
2308
2002
 
2309
- *Eileen M. Uchitelle*, *John Crepezzi*
2003
+ *Nick Holden*
2310
2004
 
2311
- * Support hash config for `structure_dump_flags` and `structure_load_flags` flags.
2312
- Now that Active Record supports multiple databases configuration,
2313
- we need a way to pass specific flags for dump/load databases since
2314
- the options are not the same for different adapters.
2315
- We can use in the original way:
2005
+ * Fix `change_column_comment` to preserve column's AUTO_INCREMENT in the MySQL adapter
2316
2006
 
2317
- ```ruby
2318
- ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = ['--no-defaults', '--skip-add-drop-table']
2319
- # or
2320
- ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = '--no-defaults --skip-add-drop-table'
2321
- ```
2007
+ *fatkodima*
2322
2008
 
2323
- And also use it passing a hash, with one or more keys, where the key
2324
- is the adapter
2009
+ * Fix quoting of `ActiveSupport::Duration` and `Rational` numbers in the MySQL adapter.
2325
2010
 
2326
- ```ruby
2327
- ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = {
2328
- mysql2: ['--no-defaults', '--skip-add-drop-table'],
2329
- postgres: '--no-tablespaces'
2330
- }
2331
- ```
2011
+ *Kevin McPhillips*
2332
2012
 
2333
- *Gustavo Gonzalez*
2013
+ * Allow column name with COLLATE (e.g., title COLLATE "C") as safe SQL string
2334
2014
 
2335
- * Connection specification now passes the "url" key as a configuration for the
2336
- adapter if the "url" protocol is "jdbc", "http", or "https". Previously only
2337
- urls with the "jdbc" prefix were passed to the Active Record Adapter, others
2338
- are assumed to be adapter specification urls.
2015
+ *Shugo Maeda*
2339
2016
 
2340
- Fixes #41137.
2017
+ * Permit underscores in the VERSION argument to database rake tasks.
2341
2018
 
2342
- *Jonathan Bracy*
2019
+ *Eddie Lebow*
2343
2020
 
2344
- * Allow to opt-out of `strict_loading` mode on a per-record base.
2021
+ * Reversed the order of `INSERT` statements in `structure.sql` dumps
2345
2022
 
2346
- This is useful when strict loading is enabled application wide or on a
2347
- model level.
2023
+ This should decrease the likelihood of merge conflicts. New migrations
2024
+ will now be added at the top of the list.
2348
2025
 
2349
- ```ruby
2350
- class User < ApplicationRecord
2351
- has_many :bookmarks
2352
- has_many :articles, strict_loading: true
2353
- end
2026
+ For existing apps, there will be a large diff the next time `structure.sql`
2027
+ is generated.
2354
2028
 
2355
- user = User.first
2356
- user.articles # => ActiveRecord::StrictLoadingViolationError
2357
- user.bookmarks # => #<ActiveRecord::Associations::CollectionProxy>
2029
+ *Alex Ghiculescu*, *Matt Larraz*
2358
2030
 
2359
- user.strict_loading!(true) # => true
2360
- user.bookmarks # => ActiveRecord::StrictLoadingViolationError
2031
+ * Fix PG.connect keyword arguments deprecation warning on ruby 2.7
2361
2032
 
2362
- user.strict_loading!(false) # => false
2363
- user.bookmarks # => #<ActiveRecord::Associations::CollectionProxy>
2364
- user.articles.strict_loading!(false) # => #<ActiveRecord::Associations::CollectionProxy>
2365
- ```
2033
+ Fixes #44307.
2366
2034
 
2367
- *Ayrton De Craene*
2035
+ *Nikita Vasilevsky*
2368
2036
 
2369
- * Add `FinderMethods#sole` and `#find_sole_by` to find and assert the
2370
- presence of exactly one record.
2037
+ * Fix dropping DB connections after serialization failures and deadlocks.
2371
2038
 
2372
- Used when you need a single row, but also want to assert that there aren't
2373
- multiple rows matching the condition; especially for when database
2374
- constraints aren't enough or are impractical.
2039
+ Prior to 6.1.4, serialization failures and deadlocks caused rollbacks to be
2040
+ issued for both real transactions and savepoints. This breaks MySQL which
2041
+ disallows rollbacks of savepoints following a deadlock.
2375
2042
 
2376
- ```ruby
2377
- Product.where(["price = %?", price]).sole
2378
- # => ActiveRecord::RecordNotFound (if no Product with given price)
2379
- # => #<Product ...> (if one Product with given price)
2380
- # => ActiveRecord::SoleRecordExceeded (if more than one Product with given price)
2043
+ 6.1.4 removed these rollbacks, for both transactions and savepoints, causing
2044
+ the DB connection to be left in an unknown state and thus discarded.
2381
2045
 
2382
- user.api_keys.find_sole_by(key: key)
2383
- # as above
2384
- ```
2046
+ These rollbacks are now restored, except for savepoints on MySQL.
2385
2047
 
2386
- *Asherah Connor*
2048
+ *Thomas Morgan*
2387
2049
 
2388
- * Makes `ActiveRecord::AttributeMethods::Query` respect the getter overrides defined in the model.
2050
+ * Make `ActiveRecord::ConnectionPool` Fiber-safe
2389
2051
 
2390
- Before:
2052
+ When `ActiveSupport::IsolatedExecutionState.isolation_level` is set to `:fiber`,
2053
+ the connection pool now supports multiple Fibers from the same Thread checking
2054
+ out connections from the pool.
2055
+
2056
+ *Alex Matchneer*
2057
+
2058
+ * Add `update_attribute!` to `ActiveRecord::Persistence`
2059
+
2060
+ Similar to `update_attribute`, but raises `ActiveRecord::RecordNotSaved` when a `before_*` callback throws `:abort`.
2391
2061
 
2392
2062
  ```ruby
2393
- class User
2394
- def admin
2395
- false # Overriding the getter to always return false
2063
+ class Topic < ActiveRecord::Base
2064
+ before_save :check_title
2065
+
2066
+ def check_title
2067
+ throw(:abort) if title == "abort"
2396
2068
  end
2397
2069
  end
2398
2070
 
2399
- user = User.first
2400
- user.update(admin: true)
2401
-
2402
- user.admin # false (as expected, due to the getter overwrite)
2403
- user.admin? # true (not expected, returned the DB column value)
2071
+ topic = Topic.create(title: "Test Title")
2072
+ # #=> #<Topic title: "Test Title">
2073
+ topic.update_attribute!(:title, "Another Title")
2074
+ # #=> #<Topic title: "Another Title">
2075
+ topic.update_attribute!(:title, "abort")
2076
+ # raises ActiveRecord::RecordNotSaved
2404
2077
  ```
2405
2078
 
2406
- After this commit, `user.admin?` above returns false, as expected.
2079
+ *Drew Tempelmeyer*
2407
2080
 
2408
- Fixes #40771.
2081
+ * Avoid loading every record in `ActiveRecord::Relation#pretty_print`
2409
2082
 
2410
- *Felipe*
2083
+ ```ruby
2084
+ # Before
2085
+ pp Foo.all # Loads the whole table.
2086
+
2087
+ # After
2088
+ pp Foo.all # Shows 10 items and an ellipsis.
2089
+ ```
2411
2090
 
2412
- * Allow delegated_type to be specified primary_key and foreign_key.
2091
+ *Ulysse Buonomo*
2413
2092
 
2414
- Since delegated_type assumes that the foreign_key ends with `_id`,
2415
- `singular_id` defined by it does not work when the foreign_key does
2416
- not end with `id`. This change fixes it by taking into account
2417
- `primary_key` and `foreign_key` in the options.
2093
+ * Change `QueryMethods#in_order_of` to drop records not listed in values.
2418
2094
 
2419
- *Ryota Egusa*
2095
+ `in_order_of` now filters down to the values provided, to match the behavior of the `Enumerable` version.
2420
2096
 
2421
- * Expose an `invert_where` method that will invert all scope conditions.
2097
+ *Kevin Newton*
2422
2098
 
2423
- ```ruby
2424
- class User
2425
- scope :active, -> { where(accepted: true, locked: false) }
2426
- end
2099
+ * Allow named expression indexes to be revertible.
2427
2100
 
2428
- User.active
2429
- # ... WHERE `accepted` = 1 AND `locked` = 0
2101
+ Previously, the following code would raise an error in a reversible migration executed while rolling back, due to the index name not being used in the index removal.
2430
2102
 
2431
- User.active.invert_where
2432
- # ... WHERE NOT (`accepted` = 1 AND `locked` = 0)
2103
+ ```ruby
2104
+ add_index(:settings, "(data->'property')", using: :gin, name: :index_settings_data_property)
2433
2105
  ```
2434
2106
 
2435
- *Kevin Deisz*
2107
+ Fixes #43331.
2108
+
2109
+ *Oliver Günther*
2436
2110
 
2437
- * Restore possibility of passing `false` to :polymorphic option of `belongs_to`.
2111
+ * Fix incorrect argument in PostgreSQL structure dump tasks.
2438
2112
 
2439
- Previously, passing `false` would trigger the option validation logic
2440
- to throw an error saying :polymorphic would not be a valid option.
2113
+ Updating the `--no-comment` argument added in Rails 7 to the correct `--no-comments` argument.
2441
2114
 
2442
- *glaszig*
2115
+ *Alex Dent*
2443
2116
 
2444
- * Remove deprecated `database` kwarg from `connected_to`.
2117
+ * Fix migration compatibility to create SQLite references/belongs_to column as integer when migration version is 6.0.
2445
2118
 
2446
- *Eileen M. Uchitelle*, *John Crepezzi*
2119
+ Reference/belongs_to in migrations with version 6.0 were creating columns as
2120
+ bigint instead of integer for the SQLite Adapter.
2447
2121
 
2448
- * Allow adding nonnamed expression indexes to be revertible.
2122
+ *Marcelo Lauxen*
2449
2123
 
2450
- Previously, the following code would raise an error, when executed while rolling back,
2451
- and the index name should be specified explicitly. Now, the index name is inferred
2452
- automatically.
2124
+ * Fix `QueryMethods#in_order_of` to handle empty order list.
2453
2125
 
2454
2126
  ```ruby
2455
- add_index(:items, "to_tsvector('english', description)")
2127
+ Post.in_order_of(:id, []).to_a
2456
2128
  ```
2457
2129
 
2458
- Fixes #40732.
2459
-
2460
- *fatkodima*
2461
-
2462
- * Only warn about negative enums if a positive form that would cause conflicts exists.
2463
-
2464
- Fixes #39065.
2465
-
2466
- *Alex Ghiculescu*
2130
+ Also more explicitly set the column as secondary order, so that any other
2131
+ value is still ordered.
2467
2132
 
2468
- * Add option to run `default_scope` on all queries.
2133
+ *Jean Boussier*
2469
2134
 
2470
- Previously, a `default_scope` would only run on select or insert queries. In some cases, like non-Rails tenant sharding solutions, it may be desirable to run `default_scope` on all queries in order to ensure queries are including a foreign key for the shard (i.e. `blog_id`).
2135
+ * Fix quoting of column aliases generated by calculation methods.
2471
2136
 
2472
- Now applications can add an option to run on all queries including select, insert, delete, and update by adding an `all_queries` option to the default scope definition.
2137
+ Since the alias is derived from the table name, we can't assume the result
2138
+ is a valid identifier.
2473
2139
 
2474
2140
  ```ruby
2475
- class Article < ApplicationRecord
2476
- default_scope -> { where(blog_id: Current.blog.id) }, all_queries: true
2141
+ class Test < ActiveRecord::Base
2142
+ self.table_name = '1abc'
2477
2143
  end
2144
+ Test.group(:id).count
2145
+ # syntax error at or near "1" (ActiveRecord::StatementInvalid)
2146
+ # LINE 1: SELECT COUNT(*) AS count_all, "1abc"."id" AS 1abc_id FROM "1...
2478
2147
  ```
2479
2148
 
2480
- *Eileen M. Uchitelle*
2149
+ *Jean Boussier*
2481
2150
 
2482
- * Add `where.associated` to check for the presence of an association.
2151
+ * Add `authenticate_by` when using `has_secure_password`.
2483
2152
 
2484
- ```ruby
2485
- # Before:
2486
- account.users.joins(:contact).where.not(contact_id: nil)
2153
+ `authenticate_by` is intended to replace code like the following, which
2154
+ returns early when a user with a matching email is not found:
2487
2155
 
2488
- # After:
2489
- account.users.where.associated(:contact)
2156
+ ```ruby
2157
+ User.find_by(email: "...")&.authenticate("...")
2490
2158
  ```
2491
2159
 
2492
- Also mirrors `where.missing`.
2160
+ Such code is vulnerable to timing-based enumeration attacks, wherein an
2161
+ attacker can determine if a user account with a given email exists. After
2162
+ confirming that an account exists, the attacker can try passwords associated
2163
+ with that email address from other leaked databases, in case the user
2164
+ re-used a password across multiple sites (a common practice). Additionally,
2165
+ knowing an account email address allows the attacker to attempt a targeted
2166
+ phishing ("spear phishing") attack.
2493
2167
 
2494
- *Kasper Timm Hansen*
2168
+ `authenticate_by` addresses the vulnerability by taking the same amount of
2169
+ time regardless of whether a user with a matching email is found:
2495
2170
 
2496
- * Allow constructors (`build_association` and `create_association`) on
2497
- `has_one :through` associations.
2171
+ ```ruby
2172
+ User.authenticate_by(email: "...", password: "...")
2173
+ ```
2498
2174
 
2499
- *Santiago Perez Perret*
2175
+ *Jonathan Hefner*
2500
2176
 
2501
2177
 
2502
- Please check [6-1-stable](https://github.com/rails/rails/blob/6-1-stable/activerecord/CHANGELOG.md) for previous changes.
2178
+ Please check [7-0-stable](https://github.com/rails/rails/blob/7-0-stable/activerecord/CHANGELOG.md) for previous changes.