activerecord 6.1.6 → 7.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (309) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1627 -983
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +18 -18
  5. data/lib/active_record/aggregations.rb +17 -14
  6. data/lib/active_record/association_relation.rb +1 -11
  7. data/lib/active_record/associations/association.rb +50 -19
  8. data/lib/active_record/associations/association_scope.rb +17 -12
  9. data/lib/active_record/associations/belongs_to_association.rb +28 -9
  10. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
  11. data/lib/active_record/associations/builder/association.rb +11 -5
  12. data/lib/active_record/associations/builder/belongs_to.rb +40 -14
  13. data/lib/active_record/associations/builder/collection_association.rb +10 -3
  14. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
  15. data/lib/active_record/associations/builder/has_many.rb +3 -2
  16. data/lib/active_record/associations/builder/has_one.rb +2 -1
  17. data/lib/active_record/associations/builder/singular_association.rb +6 -2
  18. data/lib/active_record/associations/collection_association.rb +35 -31
  19. data/lib/active_record/associations/collection_proxy.rb +30 -15
  20. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  21. data/lib/active_record/associations/foreign_association.rb +10 -3
  22. data/lib/active_record/associations/has_many_association.rb +28 -18
  23. data/lib/active_record/associations/has_many_through_association.rb +12 -7
  24. data/lib/active_record/associations/has_one_association.rb +20 -10
  25. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  26. data/lib/active_record/associations/join_dependency.rb +26 -16
  27. data/lib/active_record/associations/preloader/association.rb +207 -52
  28. data/lib/active_record/associations/preloader/batch.rb +48 -0
  29. data/lib/active_record/associations/preloader/branch.rb +147 -0
  30. data/lib/active_record/associations/preloader/through_association.rb +50 -14
  31. data/lib/active_record/associations/preloader.rb +50 -121
  32. data/lib/active_record/associations/singular_association.rb +9 -3
  33. data/lib/active_record/associations/through_association.rb +25 -14
  34. data/lib/active_record/associations.rb +439 -305
  35. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  36. data/lib/active_record/attribute_assignment.rb +1 -3
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
  38. data/lib/active_record/attribute_methods/dirty.rb +73 -22
  39. data/lib/active_record/attribute_methods/primary_key.rb +78 -26
  40. data/lib/active_record/attribute_methods/query.rb +31 -19
  41. data/lib/active_record/attribute_methods/read.rb +25 -10
  42. data/lib/active_record/attribute_methods/serialization.rb +194 -37
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
  44. data/lib/active_record/attribute_methods/write.rb +10 -13
  45. data/lib/active_record/attribute_methods.rb +121 -40
  46. data/lib/active_record/attributes.rb +27 -38
  47. data/lib/active_record/autosave_association.rb +61 -30
  48. data/lib/active_record/base.rb +25 -2
  49. data/lib/active_record/callbacks.rb +18 -34
  50. data/lib/active_record/coders/column_serializer.rb +61 -0
  51. data/lib/active_record/coders/json.rb +1 -1
  52. data/lib/active_record/coders/yaml_column.rb +70 -34
  53. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +367 -0
  54. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
  55. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +78 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +96 -590
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +172 -50
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +77 -27
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +87 -73
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +360 -138
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +281 -59
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +631 -149
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +285 -156
  69. data/lib/active_record/connection_adapters/column.rb +13 -0
  70. data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
  71. data/lib/active_record/connection_adapters/mysql/database_statements.rb +25 -134
  72. data/lib/active_record/connection_adapters/mysql/quoting.rb +56 -25
  73. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
  75. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
  76. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +38 -14
  77. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +151 -0
  78. data/lib/active_record/connection_adapters/mysql2_adapter.rb +104 -53
  79. data/lib/active_record/connection_adapters/pool_config.rb +20 -11
  80. data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
  81. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
  82. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +89 -52
  83. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  84. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
  87. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +12 -3
  89. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  92. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  93. data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -56
  94. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
  95. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
  96. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +153 -3
  97. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
  98. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +394 -74
  99. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
  100. data/lib/active_record/connection_adapters/postgresql_adapter.rb +509 -247
  101. data/lib/active_record/connection_adapters/schema_cache.rb +319 -90
  102. data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
  103. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +72 -53
  104. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +37 -21
  105. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
  106. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -22
  107. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +294 -102
  108. data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
  109. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
  110. data/lib/active_record/connection_adapters/trilogy_adapter.rb +254 -0
  111. data/lib/active_record/connection_adapters.rb +9 -6
  112. data/lib/active_record/connection_handling.rb +107 -136
  113. data/lib/active_record/core.rb +202 -223
  114. data/lib/active_record/counter_cache.rb +46 -25
  115. data/lib/active_record/database_configurations/connection_url_resolver.rb +2 -1
  116. data/lib/active_record/database_configurations/database_config.rb +21 -12
  117. data/lib/active_record/database_configurations/hash_config.rb +84 -16
  118. data/lib/active_record/database_configurations/url_config.rb +18 -12
  119. data/lib/active_record/database_configurations.rb +95 -59
  120. data/lib/active_record/delegated_type.rb +61 -15
  121. data/lib/active_record/deprecator.rb +7 -0
  122. data/lib/active_record/destroy_association_async_job.rb +3 -1
  123. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  124. data/lib/active_record/dynamic_matchers.rb +1 -1
  125. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  126. data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
  127. data/lib/active_record/encryption/cipher.rb +53 -0
  128. data/lib/active_record/encryption/config.rb +68 -0
  129. data/lib/active_record/encryption/configurable.rb +60 -0
  130. data/lib/active_record/encryption/context.rb +42 -0
  131. data/lib/active_record/encryption/contexts.rb +76 -0
  132. data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
  133. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  134. data/lib/active_record/encryption/encryptable_record.rb +224 -0
  135. data/lib/active_record/encryption/encrypted_attribute_type.rb +151 -0
  136. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  137. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  138. data/lib/active_record/encryption/encryptor.rb +155 -0
  139. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  140. data/lib/active_record/encryption/errors.rb +15 -0
  141. data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
  142. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  143. data/lib/active_record/encryption/key.rb +28 -0
  144. data/lib/active_record/encryption/key_generator.rb +53 -0
  145. data/lib/active_record/encryption/key_provider.rb +46 -0
  146. data/lib/active_record/encryption/message.rb +33 -0
  147. data/lib/active_record/encryption/message_serializer.rb +92 -0
  148. data/lib/active_record/encryption/null_encryptor.rb +21 -0
  149. data/lib/active_record/encryption/properties.rb +76 -0
  150. data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
  151. data/lib/active_record/encryption/scheme.rb +96 -0
  152. data/lib/active_record/encryption.rb +56 -0
  153. data/lib/active_record/enum.rb +154 -63
  154. data/lib/active_record/errors.rb +171 -15
  155. data/lib/active_record/explain.rb +23 -3
  156. data/lib/active_record/explain_registry.rb +11 -6
  157. data/lib/active_record/explain_subscriber.rb +1 -1
  158. data/lib/active_record/fixture_set/file.rb +15 -1
  159. data/lib/active_record/fixture_set/model_metadata.rb +14 -4
  160. data/lib/active_record/fixture_set/render_context.rb +2 -0
  161. data/lib/active_record/fixture_set/table_row.rb +70 -14
  162. data/lib/active_record/fixture_set/table_rows.rb +4 -4
  163. data/lib/active_record/fixtures.rb +131 -86
  164. data/lib/active_record/future_result.rb +164 -0
  165. data/lib/active_record/gem_version.rb +3 -3
  166. data/lib/active_record/inheritance.rb +81 -29
  167. data/lib/active_record/insert_all.rb +135 -22
  168. data/lib/active_record/integration.rb +11 -10
  169. data/lib/active_record/internal_metadata.rb +119 -33
  170. data/lib/active_record/legacy_yaml_adapter.rb +2 -39
  171. data/lib/active_record/locking/optimistic.rb +36 -21
  172. data/lib/active_record/locking/pessimistic.rb +15 -6
  173. data/lib/active_record/log_subscriber.rb +52 -19
  174. data/lib/active_record/marshalling.rb +56 -0
  175. data/lib/active_record/message_pack.rb +124 -0
  176. data/lib/active_record/middleware/database_selector/resolver.rb +10 -10
  177. data/lib/active_record/middleware/database_selector.rb +23 -13
  178. data/lib/active_record/middleware/shard_selector.rb +62 -0
  179. data/lib/active_record/migration/command_recorder.rb +112 -14
  180. data/lib/active_record/migration/compatibility.rb +221 -48
  181. data/lib/active_record/migration/default_strategy.rb +23 -0
  182. data/lib/active_record/migration/execution_strategy.rb +19 -0
  183. data/lib/active_record/migration/join_table.rb +1 -1
  184. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  185. data/lib/active_record/migration.rb +358 -171
  186. data/lib/active_record/model_schema.rb +120 -101
  187. data/lib/active_record/nested_attributes.rb +37 -18
  188. data/lib/active_record/no_touching.rb +3 -3
  189. data/lib/active_record/normalization.rb +167 -0
  190. data/lib/active_record/persistence.rb +405 -85
  191. data/lib/active_record/promise.rb +84 -0
  192. data/lib/active_record/query_cache.rb +3 -21
  193. data/lib/active_record/query_logs.rb +174 -0
  194. data/lib/active_record/query_logs_formatter.rb +41 -0
  195. data/lib/active_record/querying.rb +29 -6
  196. data/lib/active_record/railtie.rb +219 -43
  197. data/lib/active_record/railties/controller_runtime.rb +13 -9
  198. data/lib/active_record/railties/databases.rake +188 -252
  199. data/lib/active_record/railties/job_runtime.rb +23 -0
  200. data/lib/active_record/readonly_attributes.rb +41 -3
  201. data/lib/active_record/reflection.rb +241 -80
  202. data/lib/active_record/relation/batches/batch_enumerator.rb +23 -7
  203. data/lib/active_record/relation/batches.rb +192 -63
  204. data/lib/active_record/relation/calculations.rb +219 -90
  205. data/lib/active_record/relation/delegation.rb +27 -13
  206. data/lib/active_record/relation/finder_methods.rb +108 -51
  207. data/lib/active_record/relation/merger.rb +22 -13
  208. data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -3
  209. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -6
  210. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  211. data/lib/active_record/relation/predicate_builder.rb +27 -20
  212. data/lib/active_record/relation/query_attribute.rb +30 -12
  213. data/lib/active_record/relation/query_methods.rb +654 -127
  214. data/lib/active_record/relation/record_fetch_warning.rb +7 -9
  215. data/lib/active_record/relation/spawn_methods.rb +20 -3
  216. data/lib/active_record/relation/where_clause.rb +10 -19
  217. data/lib/active_record/relation.rb +262 -120
  218. data/lib/active_record/result.rb +37 -11
  219. data/lib/active_record/runtime_registry.rb +18 -13
  220. data/lib/active_record/sanitization.rb +65 -20
  221. data/lib/active_record/schema.rb +36 -22
  222. data/lib/active_record/schema_dumper.rb +73 -24
  223. data/lib/active_record/schema_migration.rb +68 -33
  224. data/lib/active_record/scoping/default.rb +72 -15
  225. data/lib/active_record/scoping/named.rb +5 -13
  226. data/lib/active_record/scoping.rb +65 -34
  227. data/lib/active_record/secure_password.rb +60 -0
  228. data/lib/active_record/secure_token.rb +21 -3
  229. data/lib/active_record/serialization.rb +6 -1
  230. data/lib/active_record/signed_id.rb +10 -8
  231. data/lib/active_record/store.rb +16 -11
  232. data/lib/active_record/suppressor.rb +13 -15
  233. data/lib/active_record/table_metadata.rb +16 -3
  234. data/lib/active_record/tasks/database_tasks.rb +225 -136
  235. data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
  236. data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
  237. data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
  238. data/lib/active_record/test_databases.rb +1 -1
  239. data/lib/active_record/test_fixtures.rb +123 -99
  240. data/lib/active_record/timestamp.rb +29 -18
  241. data/lib/active_record/token_for.rb +113 -0
  242. data/lib/active_record/touch_later.rb +11 -6
  243. data/lib/active_record/transactions.rb +48 -27
  244. data/lib/active_record/translation.rb +3 -3
  245. data/lib/active_record/type/adapter_specific_registry.rb +32 -14
  246. data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
  247. data/lib/active_record/type/internal/timezone.rb +7 -2
  248. data/lib/active_record/type/serialized.rb +9 -5
  249. data/lib/active_record/type/time.rb +4 -0
  250. data/lib/active_record/type/type_map.rb +17 -20
  251. data/lib/active_record/type.rb +1 -2
  252. data/lib/active_record/validations/absence.rb +1 -1
  253. data/lib/active_record/validations/associated.rb +4 -4
  254. data/lib/active_record/validations/numericality.rb +5 -4
  255. data/lib/active_record/validations/presence.rb +5 -28
  256. data/lib/active_record/validations/uniqueness.rb +51 -6
  257. data/lib/active_record/validations.rb +8 -4
  258. data/lib/active_record/version.rb +1 -1
  259. data/lib/active_record.rb +335 -32
  260. data/lib/arel/attributes/attribute.rb +0 -8
  261. data/lib/arel/crud.rb +28 -22
  262. data/lib/arel/delete_manager.rb +18 -4
  263. data/lib/arel/errors.rb +10 -0
  264. data/lib/arel/factory_methods.rb +4 -0
  265. data/lib/arel/filter_predications.rb +9 -0
  266. data/lib/arel/insert_manager.rb +2 -3
  267. data/lib/arel/nodes/and.rb +4 -0
  268. data/lib/arel/nodes/binary.rb +6 -1
  269. data/lib/arel/nodes/bound_sql_literal.rb +61 -0
  270. data/lib/arel/nodes/casted.rb +1 -1
  271. data/lib/arel/nodes/cte.rb +36 -0
  272. data/lib/arel/nodes/delete_statement.rb +12 -13
  273. data/lib/arel/nodes/filter.rb +10 -0
  274. data/lib/arel/nodes/fragments.rb +35 -0
  275. data/lib/arel/nodes/function.rb +1 -0
  276. data/lib/arel/nodes/homogeneous_in.rb +1 -9
  277. data/lib/arel/nodes/insert_statement.rb +2 -2
  278. data/lib/arel/nodes/leading_join.rb +8 -0
  279. data/lib/arel/nodes/node.rb +111 -2
  280. data/lib/arel/nodes/select_core.rb +2 -2
  281. data/lib/arel/nodes/select_statement.rb +2 -2
  282. data/lib/arel/nodes/sql_literal.rb +6 -0
  283. data/lib/arel/nodes/table_alias.rb +4 -0
  284. data/lib/arel/nodes/update_statement.rb +8 -3
  285. data/lib/arel/nodes.rb +5 -0
  286. data/lib/arel/predications.rb +13 -3
  287. data/lib/arel/select_manager.rb +10 -4
  288. data/lib/arel/table.rb +9 -6
  289. data/lib/arel/tree_manager.rb +0 -12
  290. data/lib/arel/update_manager.rb +18 -4
  291. data/lib/arel/visitors/dot.rb +80 -90
  292. data/lib/arel/visitors/mysql.rb +16 -3
  293. data/lib/arel/visitors/postgresql.rb +0 -10
  294. data/lib/arel/visitors/to_sql.rb +139 -19
  295. data/lib/arel/visitors/visitor.rb +2 -2
  296. data/lib/arel.rb +18 -3
  297. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  298. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  299. data/lib/rails/generators/active_record/migration.rb +3 -1
  300. data/lib/rails/generators/active_record/model/USAGE +113 -0
  301. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  302. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
  303. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  304. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  305. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  306. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  307. metadata +93 -13
  308. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  309. data/lib/active_record/null_relation.rb +0 -67
data/CHANGELOG.md CHANGED
@@ -1,1715 +1,2359 @@
1
- ## Rails 6.1.5.1 (April 26, 2022) ##
1
+ ## Rails 7.1.2 (November 10, 2023) ##
2
+
3
+ * Fix renaming primary key index when renaming a table with a UUID primary key
4
+ in PostgreSQL.
5
+
6
+ *fatkodima*
7
+
8
+ * Fix `where(field: values)` queries when `field` is a serialized attribute
9
+ (for example, when `field` uses `ActiveRecord::Base.serialize` or is a JSON
10
+ column).
11
+
12
+ *João Alves*
13
+
14
+ * Prevent marking broken connections as verified.
15
+
16
+ *Daniel Colson*
17
+
18
+ * Don't mark Float::INFINITY as changed when reassigning it
19
+
20
+ When saving a record with a float infinite value, it shouldn't mark as changed
21
+
22
+ *Maicol Bentancor*
23
+
24
+ * `ActiveRecord::Base.table_name` now returns `nil` instead of raising
25
+ "undefined method `abstract_class?` for Object:Class".
26
+
27
+ *a5-stable*
28
+
29
+ * Fix upserting for custom `:on_duplicate` and `:unique_by` consisting of all
30
+ inserts keys.
31
+
32
+ *fatkodima*
33
+
34
+ * Fixed an [issue](https://github.com/rails/rails/issues/49809) where saving a
35
+ record could innappropriately `dup` its attributes.
36
+
37
+ *Jonathan Hefner*
38
+
39
+ * Dump schema only for a specific db for rollback/up/down tasks for multiple dbs.
40
+
41
+ *fatkodima*
42
+
43
+ * Fix `NoMethodError` when casting a PostgreSQL `money` value that uses a
44
+ comma as its radix point and has no leading currency symbol. For example,
45
+ when casting `"3,50"`.
46
+
47
+ *Andreas Reischuck* and *Jonathan Hefner*
48
+
49
+ * Re-enable support for using `enum` with non-column-backed attributes.
50
+ Non-column-backed attributes must be previously declared with an explicit
51
+ type. For example:
52
+
53
+ ```ruby
54
+ class Post < ActiveRecord::Base
55
+ attribute :topic, :string
56
+ enum topic: %i[science tech engineering math]
57
+ end
58
+ ```
59
+
60
+ *Jonathan Hefner*
61
+
62
+ * Raise on `foreign_key:` being passed as an array in associations
63
+
64
+ *Nikita Vasilevsky*
65
+
66
+ * Return back maximum allowed PostgreSQL table name to 63 characters.
67
+
68
+ *fatkodima*
69
+
70
+ * Fix detecting `IDENTITY` columns for PostgreSQL < 10.
71
+
72
+ *fatkodima*
73
+
74
+
75
+ ## Rails 7.1.1 (October 11, 2023) ##
76
+
77
+ * Fix auto populating IDENTITY columns for PostgreSQL.
78
+
79
+ *fatkodima*
80
+
81
+ * Fix "ArgumentError: wrong number of arguments (given 3, expected 2)" when
82
+ down migrating `rename_table` in older migrations.
83
+
84
+ *fatkodima*
85
+
86
+ * Do not require the Action Text, Active Storage and Action Mailbox tables
87
+ to be present when running when running test on CI.
88
+
89
+ *Rafael Mendonça França*
90
+
91
+
92
+ ## Rails 7.1.0 (October 05, 2023) ##
2
93
 
3
94
  * No changes.
4
95
 
5
96
 
6
- ## Rails 6.1.5 (March 09, 2022) ##
97
+ ## Rails 7.1.0.rc2 (October 01, 2023) ##
7
98
 
8
- * Fix `ActiveRecord::ConnectionAdapters::SchemaCache#deep_deduplicate` for Ruby 2.6.
99
+ * Remove -shm and -wal SQLite files when `rails db:drop` is run.
9
100
 
10
- Ruby 2.6 and 2.7 have slightly different implementations of the `String#-@` method.
11
- In Ruby 2.6, the receiver of the `String#-@` method is modified under certain circumstances.
12
- This was later identified as a bug (https://bugs.ruby-lang.org/issues/15926) and only
13
- fixed in Ruby 2.7.
101
+ *Niklas Häusele*
14
102
 
15
- Before the changes in this commit, the
16
- `ActiveRecord::ConnectionAdapters::SchemaCache#deep_deduplicate` method, which internally
17
- calls the `String#-@` method, could also modify an input string argument in Ruby 2.6 --
18
- changing a tainted, unfrozen string into a tainted, frozen string.
103
+ * Revert the change to raise an `ArgumentError` when `#accepts_nested_attributes_for` is declared more than once for
104
+ an association in the same class.
19
105
 
20
- Fixes #43056
106
+ The reverted behavior broke the case where the `#accepts_nested_attributes_for` was defined in a concern and
107
+ where overridden in the class that included the concern.
21
108
 
22
- *Eric O'Hanlon*
109
+ *Rafael Mendonça França*
23
110
 
24
- * Fix migration compatibility to create SQLite references/belongs_to column as integer when
25
- migration version is 6.0.
26
111
 
27
- `reference`/`belongs_to` in migrations with version 6.0 were creating columns as
28
- bigint instead of integer for the SQLite Adapter.
112
+ ## Rails 7.1.0.rc1 (September 27, 2023) ##
29
113
 
30
- *Marcelo Lauxen*
114
+ * Better naming for unique constraints support.
31
115
 
32
- * Fix dbconsole for 3-tier config.
116
+ Naming unique keys leads to misunderstanding it's a short-hand of unique indexes.
117
+ Just naming it unique constraints is not misleading.
33
118
 
34
- *Eileen M. Uchitelle*
119
+ In Rails 7.1.0.beta1 or before:
120
+
121
+ ```ruby
122
+ add_unique_key :sections, [:position], deferrable: :deferred, name: "unique_section_position"
123
+ remove_unique_key :sections, name: "unique_section_position"
124
+ ```
35
125
 
36
- * Better handle SQL queries with invalid encoding.
126
+ Now:
37
127
 
38
128
  ```ruby
39
- Post.create(name: "broken \xC8 UTF-8")
129
+ add_unique_constraint :sections, [:position], deferrable: :deferred, name: "unique_section_position"
130
+ remove_unique_constraint :sections, name: "unique_section_position"
40
131
  ```
41
132
 
42
- Would cause all adapters to fail in a non controlled way in the code
43
- responsible to detect write queries.
133
+ *Ryuta Kamizono*
44
134
 
45
- The query is now properly passed to the database connection, which might or might
46
- not be able to handle it, but will either succeed or failed in a more correct way.
135
+ * Fix duplicate quoting for check constraint expressions in schema dump when using MySQL
47
136
 
48
- *Jean Boussier*
137
+ A check constraint with an expression, that already contains quotes, lead to an invalid schema
138
+ dump with the mysql2 adapter.
49
139
 
50
- * Ignore persisted in-memory records when merging target lists.
140
+ Fixes #42424.
51
141
 
52
- *Kevin Sjöberg*
142
+ *Felix Tscheulin*
53
143
 
54
- * Fix regression bug that caused ignoring additional conditions for preloading
55
- `has_many` through relations.
144
+ * Performance tune the SQLite3 adapter connection configuration
56
145
 
57
- Fixes #43132
146
+ For Rails applications, the Write-Ahead-Log in normal syncing mode with a capped journal size, a healthy shared memory buffer and a shared cache will perform, on average, 2× better.
58
147
 
59
- *Alexander Pauly*
148
+ *Stephen Margheim*
60
149
 
61
- * Fix `ActiveRecord::InternalMetadata` to not be broken by
62
- `config.active_record.record_timestamps = false`
150
+ * Allow SQLite3 `busy_handler` to be configured with simple max number of `retries`
63
151
 
64
- Since the model always create the timestamp columns, it has to set them, otherwise it breaks
65
- various DB management tasks.
152
+ Retrying busy connections without delay is a preferred practice for performance-sensitive applications. Add support for a `database.yml` `retries` integer, which is used in a simple `busy_handler` function to retry busy connections without exponential backoff up to the max number of `retries`.
66
153
 
67
- Fixes #42983
154
+ *Stephen Margheim*
68
155
 
69
- *Jean Boussier*
156
+ * The SQLite3 adapter now supports `supports_insert_returning?`
70
157
 
71
- * Fix duplicate active record objects on `inverse_of`.
158
+ Implementing the full `supports_insert_returning?` contract means the SQLite3 adapter supports auto-populated columns (#48241) as well as custom primary keys.
72
159
 
73
- *Justin Carvalho*
160
+ *Stephen Margheim*
74
161
 
75
- * Fix duplicate objects stored in has many association after save.
162
+ * Ensure the SQLite3 adapter handles default functions with the `||` concatenation operator
76
163
 
77
- Fixes #42549.
164
+ Previously, this default function would produce the static string `"'Ruby ' || 'on ' || 'Rails'"`.
165
+ Now, the adapter will appropriately receive and use `"Ruby on Rails"`.
78
166
 
79
- *Alex Ghiculescu*
167
+ ```ruby
168
+ change_column_default "test_models", "ruby_on_rails", -> { "('Ruby ' || 'on ' || 'Rails')" }
169
+ ```
170
+
171
+ *Stephen Margheim*
172
+
173
+ * Dump PostgreSQL schemas as part of the schema dump.
174
+
175
+ *Lachlan Sylvester*
176
+
177
+
178
+ ## Rails 7.1.0.beta1 (September 13, 2023) ##
80
179
 
81
- * Fix performance regression in `CollectionAssocation#build`.
180
+ * Encryption now supports `support_unencrypted_data` being set per-attribute.
181
+
182
+ You can now opt out of `support_unencrypted_data` on a specific encrypted attribute.
183
+ This only has an effect if `ActiveRecord::Encryption.config.support_unencrypted_data == true`.
184
+
185
+ ```ruby
186
+ class User < ActiveRecord::Base
187
+ encrypts :name, deterministic: true, support_unencrypted_data: false
188
+ encrypts :email, deterministic: true
189
+ end
190
+ ```
82
191
 
83
192
  *Alex Ghiculescu*
84
193
 
85
- * Fix retrieving default value for text column for MariaDB.
194
+ * Add instrumentation for Active Record transactions
195
+
196
+ Allows subscribing to transaction events for tracking/instrumentation. The event payload contains the connection and the outcome (commit, rollback, restart, incomplete), as well as timing details.
197
+
198
+ ```ruby
199
+ ActiveSupport::Notifications.subscribe("transaction.active_record") do |event|
200
+ puts "Transaction event occurred!"
201
+ connection = event.payload[:connection]
202
+ puts "Connection: #{connection.inspect}"
203
+ end
204
+ ```
205
+
206
+ *Daniel Colson*, *Ian Candy*
207
+
208
+ * Support composite foreign keys via migration helpers.
209
+
210
+ ```ruby
211
+ # Assuming "carts" table has "(shop_id, user_id)" as a primary key.
212
+
213
+ add_foreign_key(:orders, :carts, primary_key: [:shop_id, :user_id])
214
+
215
+ remove_foreign_key(:orders, :carts, primary_key: [:shop_id, :user_id])
216
+ foreign_key_exists?(:orders, :carts, primary_key: [:shop_id, :user_id])
217
+ ```
86
218
 
87
219
  *fatkodima*
88
220
 
221
+ * Adds support for `if_not_exists` when adding a check constraint.
89
222
 
90
- ## Rails 6.1.4.7 (March 08, 2022) ##
223
+ ```ruby
224
+ add_check_constraint :posts, "post_type IN ('blog', 'comment', 'share')", if_not_exists: true
225
+ ```
91
226
 
92
- * No changes.
227
+ *Cody Cutrer*
93
228
 
229
+ * Raise an `ArgumentError` when `#accepts_nested_attributes_for` is declared more than once for an association in
230
+ the same class. Previously, the last declaration would silently override the previous one. Overriding in a subclass
231
+ is still allowed.
94
232
 
95
- ## Rails 6.1.4.6 (February 11, 2022) ##
233
+ *Joshua Young*
96
234
 
97
- * No changes.
235
+ * Deprecate `rewhere` argument on `#merge`.
98
236
 
237
+ The `rewhere` argument on `#merge`is deprecated without replacement and
238
+ will be removed in Rails 7.2.
99
239
 
100
- ## Rails 6.1.4.5 (February 11, 2022) ##
240
+ *Adam Hess*
101
241
 
102
- * No changes.
242
+ * Deprecate aliasing non-attributes with `alias_attribute`.
103
243
 
244
+ *Ian Candy*
104
245
 
105
- ## Rails 6.1.4.4 (December 15, 2021) ##
246
+ * Fix unscope is not working in specific case
106
247
 
107
- * No changes.
248
+ Before:
249
+ ```ruby
250
+ Post.where(id: 1...3).unscope(where: :id).to_sql # "SELECT `posts`.* FROM `posts` WHERE `posts`.`id` >= 1 AND `posts`.`id` < 3"
251
+
252
+ ```
253
+
254
+ After:
255
+ ```ruby
256
+ Post.where(id: 1...3).unscope(where: :id).to_sql # "SELECT `posts`.* FROM `posts`"
257
+ ```
108
258
 
259
+ Fixes #48094.
109
260
 
110
- ## Rails 6.1.4.3 (December 14, 2021) ##
261
+ *Kazuya Hatanaka*
111
262
 
112
- * No changes.
263
+ * Change `has_secure_token` default to `on: :initialize`
113
264
 
265
+ Change the new default value from `on: :create` to `on: :initialize`
114
266
 
115
- ## Rails 6.1.4.2 (December 14, 2021) ##
267
+ Can be controlled by the `config.active_record.generate_secure_token_on`
268
+ configuration:
116
269
 
117
- * No changes.
270
+ ```ruby
271
+ config.active_record.generate_secure_token_on = :create
272
+ ```
118
273
 
274
+ *Sean Doyle*
119
275
 
120
- ## Rails 6.1.4.1 (August 19, 2021) ##
276
+ * Fix `change_column` not setting `precision: 6` on `datetime` columns when
277
+ using 7.0+ Migrations and SQLite.
121
278
 
122
- * No changes.
279
+ *Hartley McGuire*
123
280
 
281
+ * Support composite identifiers in `to_key`
124
282
 
125
- ## Rails 6.1.4 (June 24, 2021) ##
283
+ `to_key` avoids wrapping `#id` value into an `Array` if `#id` already an array
126
284
 
127
- * Do not try to rollback transactions that failed due to a `ActiveRecord::TransactionRollbackError`.
285
+ *Nikita Vasilevsky*
128
286
 
129
- *Jamie McCarthy*
287
+ * Add validation option for `enum`
130
288
 
131
- * Raise an error if `pool_config` is `nil` in `set_pool_config`.
289
+ ```ruby
290
+ class Contract < ApplicationRecord
291
+ enum :status, %w[in_progress completed], validate: true
292
+ end
293
+ Contract.new(status: "unknown").valid? # => false
294
+ Contract.new(status: nil).valid? # => false
295
+ Contract.new(status: "completed").valid? # => true
132
296
 
133
- *Eileen M. Uchitelle*
297
+ class Contract < ApplicationRecord
298
+ enum :status, %w[in_progress completed], validate: { allow_nil: true }
299
+ end
300
+ Contract.new(status: "unknown").valid? # => false
301
+ Contract.new(status: nil).valid? # => true
302
+ Contract.new(status: "completed").valid? # => true
303
+ ```
134
304
 
135
- * Fix compatibility with `psych >= 4`.
305
+ *Edem Topuzov*, *Ryuta Kamizono*
136
306
 
137
- Starting in Psych 4.0.0 `YAML.load` behaves like `YAML.safe_load`. To preserve compatibility
138
- Active Record's schema cache loader and `YAMLColumn` now uses `YAML.unsafe_load` if available.
307
+ * Allow batching methods to use already loaded relation if available
139
308
 
140
- *Jean Boussier*
309
+ Calling batch methods on already loaded relations will use the records previously loaded instead of retrieving
310
+ them from the database again.
141
311
 
142
- * Support using replicas when using `rails dbconsole`.
312
+ *Adam Hess*
143
313
 
144
- *Christopher Thornton*
314
+ * Deprecate `read_attribute(:id)` returning the primary key if the primary key is not `:id`.
145
315
 
146
- * Restore connection pools after transactional tests.
316
+ Starting in Rails 7.2, `read_attribute(:id)` will return the value of the id column, regardless of the model's
317
+ primary key. To retrieve the value of the primary key, use `#id` instead. `read_attribute(:id)` for composite
318
+ primary key models will now return the value of the id column.
147
319
 
148
- *Eugene Kenny*
320
+ *Adrianna Chang*
149
321
 
150
- * Change `upsert_all` to fails cleanly for MySQL when `:unique_by` is used.
322
+ * Fix `change_table` setting datetime precision for 6.1 Migrations
151
323
 
152
- *Bastian Bartmann*
324
+ *Hartley McGuire*
153
325
 
154
- * Fix user-defined `self.default_scope` to respect table alias.
326
+ * Fix change_column setting datetime precision for 6.1 Migrations
155
327
 
156
- *Ryuta Kamizono*
328
+ *Hartley McGuire*
157
329
 
158
- * Clear `@cache_keys` cache after `update_all`, `delete_all`, `destroy_all`.
330
+ * Add `ActiveRecord::Base#id_value` alias to access the raw value of a record's id column.
159
331
 
160
- *Ryuta Kamizono*
332
+ This alias is only provided for models that declare an `:id` column.
161
333
 
162
- * Changed Arel predications `contains` and `overlaps` to use
163
- `quoted_node` so that PostgreSQL arrays are quoted properly.
334
+ *Adrianna Chang*
164
335
 
165
- *Bradley Priest*
336
+ * Fix previous change tracking for `ActiveRecord::Store` when using a column with JSON structured database type
166
337
 
167
- * Fix `merge` when the `where` clauses have string contents.
338
+ 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
168
339
 
169
- *Ryuta Kamizono*
340
+ *Robert DiMartino*
341
+
342
+ * Fully support `NULLS [NOT] DISTINCT` for PostgreSQL 15+ indexes.
170
343
 
171
- * Fix rollback of parent destruction with nested `dependent: :destroy`.
344
+ Previous work was done to allow the index to be created in a migration, but it was not
345
+ supported in schema.rb. Additionally, the matching for `NULLS [NOT] DISTINCT` was not
346
+ in the correct order, which could have resulted in inconsistent schema detection.
172
347
 
173
- *Jacopo Beschi*
348
+ *Gregory Jones*
174
349
 
175
- * Fix binds logging for `"WHERE ... IN ..."` statements.
350
+ * Allow escaping of literal colon characters in `sanitize_sql_*` methods when named bind variables are used
176
351
 
177
- *Ricardo Díaz*
352
+ *Justin Bull*
178
353
 
179
- * Handle `false` in relation strict loading checks.
354
+ * Fix `#previously_new_record?` to return true for destroyed records.
180
355
 
181
- Previously when a model had strict loading set to true and then had a
182
- relation set `strict_loading` to false the false wasn't considered when
183
- deciding whether to raise/warn about strict loading.
356
+ Before, if a record was created and then destroyed, `#previously_new_record?` would return true.
357
+ Now, any UPDATE or DELETE to a record is considered a change, and will result in `#previously_new_record?`
358
+ returning false.
184
359
 
360
+ *Adrianna Chang*
361
+
362
+ * Specify callback in `has_secure_token`
363
+
364
+ ```ruby
365
+ class User < ApplicationRecord
366
+ has_secure_token on: :initialize
367
+ end
368
+
369
+ User.new.token # => "abc123...."
185
370
  ```
186
- class Dog < ActiveRecord::Base
187
- self.strict_loading_by_default = true
188
371
 
189
- has_many :treats, strict_loading: false
372
+ *Sean Doyle*
373
+
374
+ * Fix incrementation of in memory counter caches when associations overlap
375
+
376
+ When two associations had a similarly named counter cache column, Active Record
377
+ could sometime increment the wrong one.
378
+
379
+ *Jacopo Beschi*, *Jean Boussier*
380
+
381
+ * Don't show secrets for Active Record's `Cipher::Aes256Gcm#inspect`.
382
+
383
+ Before:
384
+
385
+ ```ruby
386
+ ActiveRecord::Encryption::Cipher::Aes256Gcm.new(secret).inspect
387
+ "#<ActiveRecord::Encryption::Cipher::Aes256Gcm:0x0000000104888038 ... @secret=\"\\xAF\\bFh]LV}q\\nl\\xB2U\\xB3 ... >"
388
+ ```
389
+
390
+ After:
391
+
392
+ ```ruby
393
+ ActiveRecord::Encryption::Cipher::Aes256Gcm(secret).inspect
394
+ "#<ActiveRecord::Encryption::Cipher::Aes256Gcm:0x0000000104888038>"
395
+ ```
396
+
397
+ *Petrik de Heus*
398
+
399
+ * Bring back the historical behavior of committing transaction on non-local return.
400
+
401
+ ```ruby
402
+ Model.transaction do
403
+ model.save
404
+ return
405
+ other_model.save # not executed
190
406
  end
191
407
  ```
192
408
 
193
- In the example, `dog.treats` would still raise even though
194
- `strict_loading` was set to false. This is a bug affecting more than
195
- Active Storage which is why I made this PR superseding #41461. We need
196
- to fix this for all applications since the behavior is a little
197
- surprising. I took the test from #41461 and the code suggestion from #41453
198
- with some additions.
409
+ Historically only raised errors would trigger a rollback, but in Ruby `2.3`, the `timeout` library
410
+ started using `throw` to interrupt execution which had the adverse effect of committing open transactions.
199
411
 
200
- *Eileen M. Uchitelle*, *Radamés Roriz*
412
+ To solve this, in Active Record 6.1 the behavior was changed to instead rollback the transaction as it was safer
413
+ than to potentially commit an incomplete transaction.
201
414
 
202
- * Fix numericality validator without precision.
415
+ Using `return`, `break` or `throw` inside a `transaction` block was essentially deprecated from Rails 6.1 onwards.
203
416
 
204
- *Ryuta Kamizono*
417
+ However with the release of `timeout 0.4.0`, `Timeout.timeout` now raises an error again, and Active Record is able
418
+ to return to its original, less surprising, behavior.
205
419
 
206
- * Fix aggregate attribute on Enum types.
420
+ This historical behavior can now be opt-ed in via:
207
421
 
208
- *Ryuta Kamizono*
422
+ ```
423
+ Rails.application.config.active_record.commit_transaction_on_non_local_return = true
424
+ ```
425
+
426
+ And is the default for new applications created in Rails 7.1.
209
427
 
210
- * Fix `CREATE INDEX` statement generation for PostgreSQL.
428
+ *Jean Boussier*
211
429
 
212
- *eltongo*
430
+ * Deprecate `name` argument on `#remove_connection`.
213
431
 
214
- * Fix where clause on enum attribute when providing array of strings.
432
+ The `name` argument is deprecated on `#remove_connection` without replacement. `#remove_connection` should be called directly on the class that established the connection.
215
433
 
216
- *Ryuta Kamizono*
434
+ *Eileen M. Uchitelle*
217
435
 
218
- * Fix `unprepared_statement` to work it when nesting.
436
+ * Fix has_one through singular building with inverse.
219
437
 
220
- *Ryuta Kamizono*
438
+ Allows building of records from an association with a has_one through a
439
+ singular association with inverse. For belongs_to through associations,
440
+ linking the foreign key to the primary key model isn't needed.
441
+ For has_one, we cannot build records due to the association not being mutable.
221
442
 
443
+ *Gannon McGibbon*
222
444
 
223
- ## Rails 6.1.3.2 (May 05, 2021) ##
445
+ * Disable database prepared statements when query logs are enabled
224
446
 
225
- * No changes.
447
+ Prepared Statements and Query Logs are incompatible features due to query logs making every query unique.
226
448
 
449
+ *zzak, Jean Boussier*
227
450
 
228
- ## Rails 6.1.3.1 (March 26, 2021) ##
451
+ * Support decrypting data encrypted non-deterministically with a SHA1 hash digest.
229
452
 
230
- * No changes.
453
+ This adds a new Active Record encryption option to support decrypting data encrypted
454
+ non-deterministically with a SHA1 hash digest:
231
455
 
456
+ ```
457
+ Rails.application.config.active_record.encryption.support_sha1_for_non_deterministic_encryption = true
458
+ ```
232
459
 
233
- ## Rails 6.1.3 (February 17, 2021) ##
460
+ The new option addresses a problem when upgrading from 7.0 to 7.1. Due to a bug in how Active Record
461
+ Encryption was getting initialized, the key provider used for non-deterministic encryption were using
462
+ SHA-1 as its digest class, instead of the one configured globally by Rails via
463
+ `Rails.application.config.active_support.key_generator_hash_digest_class`.
234
464
 
235
- * Fix the MySQL adapter to always set the right collation and charset
236
- to the connection session.
465
+ *Cadu Ribeiro and Jorge Manrubia*
237
466
 
238
- *Rafael Mendonça França*
467
+ * Added PostgreSQL migration commands for enum rename, add value, and rename value.
239
468
 
240
- * Fix MySQL adapter handling of time objects when prepared statements
241
- are enabled.
469
+ `rename_enum` and `rename_enum_value` are reversible. Due to Postgres
470
+ limitation, `add_enum_value` is not reversible since you cannot delete enum
471
+ values. As an alternative you should drop and recreate the enum entirely.
242
472
 
243
- *Rafael Mendonça França*
473
+ ```ruby
474
+ rename_enum :article_status, to: :article_state
475
+ ```
244
476
 
245
- * Fix scoping in enum fields using conditions that would generate
246
- an `IN` clause.
477
+ ```ruby
478
+ add_enum_value :article_state, "archived" # will be at the end of existing values
479
+ add_enum_value :article_state, "in review", before: "published"
480
+ add_enum_value :article_state, "approved", after: "in review"
481
+ ```
247
482
 
248
- *Ryuta Kamizono*
483
+ ```ruby
484
+ rename_enum_value :article_state, from: "archived", to: "deleted"
485
+ ```
249
486
 
250
- * Skip optimised #exist? query when #include? is called on a relation
251
- with a having clause
487
+ *Ray Faddis*
252
488
 
253
- Relations that have aliased select values AND a having clause that
254
- references an aliased select value would generate an error when
255
- #include? was called, due to an optimisation that would generate
256
- call #exists? on the relation instead, which effectively alters
257
- the select values of the query (and thus removes the aliased select
258
- values), but leaves the having clause intact. Because the having
259
- clause is then referencing an aliased column that is no longer
260
- present in the simplified query, an ActiveRecord::InvalidStatement
261
- error was raised.
489
+ * Allow composite primary key to be derived from schema
262
490
 
263
- An sample query affected by this problem:
491
+ Booting an application with a schema that contains composite primary keys
492
+ will not issue warning and won't `nil`ify the `ActiveRecord::Base#primary_key` value anymore.
264
493
 
494
+ Given a `travel_routes` table definition and a `TravelRoute` model like:
265
495
  ```ruby
266
- Author.select('COUNT(*) as total_posts', 'authors.*')
267
- .joins(:posts)
268
- .group(:id)
269
- .having('total_posts > 2')
270
- .include?(Author.first)
496
+ create_table :travel_routes, primary_key: [:origin, :destination], force: true do |t|
497
+ t.string :origin
498
+ t.string :destination
499
+ end
500
+
501
+ class TravelRoute < ActiveRecord::Base; end
271
502
  ```
503
+ The `TravelRoute.primary_key` value will be automatically derived to `["origin", "destination"]`
272
504
 
273
- This change adds an addition check to the condition that skips the
274
- simplified #exists? query, which simply checks for the presence of
275
- a having clause.
505
+ *Nikita Vasilevsky*
276
506
 
277
- Fixes #41417
507
+ * Include the `connection_pool` with exceptions raised from an adapter.
278
508
 
279
- *Michael Smart*
509
+ The `connection_pool` provides added context such as the connection used
510
+ that led to the exception as well as which role and shard.
280
511
 
281
- * Increment postgres prepared statement counter before making a prepared statement, so if the statement is aborted
282
- without Rails knowledge (e.g., if app gets kill -9d during long-running query or due to Rack::Timeout), app won't end
283
- up in perpetual crash state for being inconsistent with Postgres.
512
+ *Luan Vieira*
284
513
 
285
- *wbharding*, *Martin Tepper*
514
+ * Support multiple column ordering for `find_each`, `find_in_batches` and `in_batches`.
286
515
 
516
+ 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.
287
517
 
288
- ## Rails 6.1.2.1 (February 10, 2021) ##
518
+ ```ruby
519
+ Person.find_each(order: [:desc, :asc]) do |person|
520
+ person.party_all_night!
521
+ end
522
+ ```
289
523
 
290
- * Fix possible DoS vector in PostgreSQL money type
524
+ *Takuya Kurimoto*
291
525
 
292
- Carefully crafted input can cause a DoS via the regular expressions used
293
- for validating the money format in the PostgreSQL adapter. This patch
294
- fixes the regexp.
526
+ * Fix where on association with has_one/has_many polymorphic relations.
295
527
 
296
- Thanks to @dee-see from Hackerone for this patch!
528
+ Before:
529
+ ```ruby
530
+ Treasure.where(price_estimates: PriceEstimate.all)
531
+ #=> SELECT (...) WHERE "treasures"."id" IN (SELECT "price_estimates"."estimate_of_id" FROM "price_estimates")
532
+ ```
297
533
 
298
- [CVE-2021-22880]
534
+ Later:
535
+ ```ruby
536
+ Treasure.where(price_estimates: PriceEstimate.all)
537
+ #=> SELECT (...) WHERE "treasures"."id" IN (SELECT "price_estimates"."estimate_of_id" FROM "price_estimates" WHERE "price_estimates"."estimate_of_type" = 'Treasure')
538
+ ```
299
539
 
300
- *Aaron Patterson*
540
+ *Lázaro Nixon*
301
541
 
542
+ * Assign auto populated columns on Active Record record creation.
302
543
 
303
- ## Rails 6.1.2 (February 09, 2021) ##
544
+ Changes record creation logic to allow for the `auto_increment` column to be assigned
545
+ immediately after creation regardless of it's relation to the model's primary key.
304
546
 
305
- * Fix timestamp type for sqlite3.
547
+ The PostgreSQL adapter benefits the most from the change allowing for any number of auto-populated
548
+ columns to be assigned on the object immediately after row insertion utilizing the `RETURNING` statement.
549
+
550
+ *Nikita Vasilevsky*
551
+
552
+ * Use the first key in the `shards` hash from `connected_to` for the `default_shard`.
553
+
554
+ 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.
555
+
556
+ For example if your model looked like this:
557
+
558
+ ```ruby
559
+ class ShardRecord < ApplicationRecord
560
+ self.abstract_class = true
561
+
562
+ connects_to shards: {
563
+ shard_one: { writing: :shard_one },
564
+ shard_two: { writing: :shard_two }
565
+ }
566
+ ```
567
+
568
+ Then the `default_shard` for this class would be set to `shard_one`.
569
+
570
+ Fixes: #45390
306
571
 
307
572
  *Eileen M. Uchitelle*
308
573
 
309
- * Make destroy async transactional.
574
+ * Fix mutation detection for serialized attributes backed by binary columns.
310
575
 
311
- An active record rollback could occur while enqueuing a job. In this
312
- case the job would enqueue even though the database deletion
313
- rolledback putting things in a funky state.
576
+ *Jean Boussier*
314
577
 
315
- Now the jobs are only enqueued until after the db transaction has been committed.
578
+ * Add `ActiveRecord.disconnect_all!` method to immediately close all connections from all pools.
316
579
 
317
- *Cory Gwin*
580
+ *Jean Boussier*
318
581
 
319
- * Fix malformed packet error in MySQL statement for connection configuration.
582
+ * Discard connections which may have been left in a transaction.
320
583
 
321
- *robinroestenburg*
584
+ 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:
585
+ - Writes appear to fail when they actually succeed.
586
+ - Writes appear to succeed when they actually fail.
587
+ - Reads return stale or uncommitted data.
322
588
 
323
- * Connection specification now passes the "url" key as a configuration for the
324
- adapter if the "url" protocol is "jdbc", "http", or "https". Previously only
325
- urls with the "jdbc" prefix were passed to the Active Record Adapter, others
326
- are assumed to be adapter specification urls.
589
+ Previously, the following case was detected:
590
+ - An error is encountered during the transaction, then another error is encountered while attempting to roll it back.
327
591
 
328
- Fixes #41137.
592
+ Now, the following additional cases are detected:
593
+ - An error is encountered just after successfully beginning a transaction.
594
+ - An error is encountered while committing a transaction, then another error is encountered while attempting to roll it back.
595
+ - An error is encountered while rolling back a transaction.
329
596
 
330
- *Jonathan Bracy*
597
+ *Nick Dower*
331
598
 
332
- * Fix granular connection swapping when there are multiple abstract classes.
599
+ * Active Record query cache now evicts least recently used entries
333
600
 
334
- *Eileen M. Uchitelle*
601
+ By default it only keeps the `100` most recently used queries.
335
602
 
336
- * Fix `find_by` with custom primary key for belongs_to association.
603
+ The cache size can be configured via `database.yml`
337
604
 
338
- *Ryuta Kamizono*
605
+ ```yaml
606
+ development:
607
+ adapter: mysql2
608
+ query_cache: 200
609
+ ```
339
610
 
340
- * Add support for `rails console --sandbox` for multiple database applications.
611
+ It can also be entirely disabled:
341
612
 
342
- *alpaca-tc*
613
+ ```yaml
614
+ development:
615
+ adapter: mysql2
616
+ query_cache: false
617
+ ```
343
618
 
344
- * Fix `where` on polymorphic association with empty array.
619
+ *Jean Boussier*
345
620
 
346
- *Ryuta Kamizono*
621
+ * Deprecate `check_pending!` in favor of `check_all_pending!`.
347
622
 
348
- * Fix preventing writes for `ApplicationRecord`.
623
+ `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.
349
624
 
350
625
  *Eileen M. Uchitelle*
351
626
 
627
+ * Make `increment_counter`/`decrement_counter` accept an amount argument
352
628
 
353
- ## Rails 6.1.1 (January 07, 2021) ##
629
+ ```ruby
630
+ Post.increment_counter(:comments_count, 5, by: 3)
631
+ ```
354
632
 
355
- * Fix fixtures loading when strict loading is enabled for the association.
633
+ *fatkodima*
356
634
 
357
- *Alex Ghiculescu*
635
+ * Add support for `Array#intersect?` to `ActiveRecord::Relation`.
358
636
 
359
- * Fix `where` with custom primary key for belongs_to association.
637
+ `Array#intersect?` is only available on Ruby 3.1 or later.
360
638
 
361
- *Ryuta Kamizono*
639
+ This allows the Rubocop `Style/ArrayIntersect` cop to work with `ActiveRecord::Relation` objects.
362
640
 
363
- * Fix `where` with aliased associations.
641
+ *John Harry Kelly*
364
642
 
365
- *Ryuta Kamizono*
643
+ * The deferrable foreign key can be passed to `t.references`.
366
644
 
367
- * Fix `composed_of` with symbol mapping.
645
+ *Hiroyuki Ishii*
368
646
 
369
- *Ryuta Kamizono*
647
+ * Deprecate `deferrable: true` option of `add_foreign_key`.
370
648
 
371
- * Don't skip money's type cast for pluck and calculations.
649
+ `deferrable: true` is deprecated in favor of `deferrable: :immediate`, and
650
+ will be removed in Rails 7.2.
372
651
 
373
- *Ryuta Kamizono*
652
+ Because `deferrable: true` and `deferrable: :deferred` are hard to understand.
653
+ Both true and :deferred are truthy values.
654
+ This behavior is the same as the deferrable option of the add_unique_key method, added in #46192.
374
655
 
375
- * Fix `where` on polymorphic association with non Active Record object.
656
+ *Hiroyuki Ishii*
376
657
 
377
- *Ryuta Kamizono*
658
+ * `AbstractAdapter#execute` and `#exec_query` now clear the query cache
378
659
 
379
- * Make sure `db:prepare` works even the schema file doesn't exist.
660
+ If you need to perform a read only SQL query without clearing the query
661
+ cache, use `AbstractAdapter#select_all`.
380
662
 
381
- *Rafael Mendonça França*
663
+ *Jean Boussier*
382
664
 
383
- * Fix complicated `has_many :through` with nested where condition.
665
+ * Make `.joins` / `.left_outer_joins` work with CTEs.
384
666
 
385
- *Ryuta Kamizono*
667
+ For example:
386
668
 
387
- * Handle STI models for `has_many dependent: :destroy_async`.
669
+ ```ruby
670
+ Post
671
+ .with(commented_posts: Comment.select(:post_id).distinct)
672
+ .joins(:commented_posts)
673
+ #=> WITH (...) SELECT ... INNER JOIN commented_posts on posts.id = commented_posts.post_id
674
+ ```
388
675
 
389
- *Muhammad Usman*
676
+ *Vladimir Dementyev*
390
677
 
391
- * Restore possibility of passing `false` to :polymorphic option of `belongs_to`.
678
+ * Add a load hook for `ActiveRecord::ConnectionAdapters::Mysql2Adapter`
679
+ (named `active_record_mysql2adapter`) to allow for overriding aspects of the
680
+ `ActiveRecord::ConnectionAdapters::Mysql2Adapter` class. This makes `Mysql2Adapter`
681
+ consistent with `PostgreSQLAdapter` and `SQLite3Adapter` that already have load hooks.
392
682
 
393
- Previously, passing `false` would trigger the option validation logic
394
- to throw an error saying :polymorphic would not be a valid option.
683
+ *fatkodima*
395
684
 
396
- *glaszig*
685
+ * Introduce adapter for Trilogy database client
397
686
 
398
- * Allow adding nonnamed expression indexes to be revertible.
687
+ Trilogy is a MySQL-compatible database client. Rails applications can use Trilogy
688
+ by configuring their `config/database.yml`:
399
689
 
400
- Fixes #40732.
690
+ ```yaml
691
+ development:
692
+ adapter: trilogy
693
+ database: blog_development
694
+ pool: 5
695
+ ```
401
696
 
402
- Previously, the following code would raise an error, when executed while rolling back,
403
- and the index name should be specified explicitly. Now, the index name is inferred
404
- automatically.
697
+ Or by using the `DATABASE_URL` environment variable:
405
698
 
406
699
  ```ruby
407
- add_index(:items, "to_tsvector('english', description)")
700
+ ENV['DATABASE_URL'] # => "trilogy://localhost/blog_development?pool=5"
408
701
  ```
409
702
 
410
- *fatkodima*
703
+ *Adrianna Chang*
411
704
 
705
+ * `after_commit` callbacks defined on models now execute in the correct order.
412
706
 
413
- ## Rails 6.1.0 (December 09, 2020) ##
707
+ ```ruby
708
+ class User < ActiveRecord::Base
709
+ after_commit { puts("this gets called first") }
710
+ after_commit { puts("this gets called second") }
711
+ end
712
+ ```
414
713
 
415
- * Only warn about negative enums if a positive form that would cause conflicts exists.
714
+ Previously, the callbacks executed in the reverse order. To opt in to the new behaviour:
715
+
716
+ ```ruby
717
+ config.active_record.run_after_transaction_callbacks_in_order_defined = true
718
+ ```
416
719
 
417
- Fixes #39065.
720
+ This is the default for new apps.
418
721
 
419
722
  *Alex Ghiculescu*
420
723
 
421
- * Change `attribute_for_inspect` to take `filter_attributes` in consideration.
724
+ * Infer `foreign_key` when `inverse_of` is present on `has_one` and `has_many` associations.
422
725
 
423
- *Rafael Mendonça França*
726
+ ```ruby
727
+ has_many :citations, foreign_key: "book1_id", inverse_of: :book
728
+ ```
729
+
730
+ can be simplified to
731
+
732
+ ```ruby
733
+ has_many :citations, inverse_of: :book
734
+ ```
735
+
736
+ and the foreign_key will be read from the corresponding `belongs_to` association.
737
+
738
+ *Daniel Whitney*
739
+
740
+ * Limit max length of auto generated index names
741
+
742
+ Auto generated index names are now limited to 62 bytes, which fits within
743
+ the default index name length limits for MySQL, Postgres and SQLite.
424
744
 
425
- * Fix odd behavior of inverse_of with multiple belongs_to to same class.
745
+ Any index name over the limit will fallback to the new short format.
426
746
 
427
- Fixes #35204.
747
+ Before (too long):
748
+ ```
749
+ index_testings_on_foo_and_bar_and_first_name_and_last_name_and_administrator
750
+ ```
751
+
752
+ After (short format):
753
+ ```
754
+ idx_on_foo_bar_first_name_last_name_administrator_5939248142
755
+ ```
756
+
757
+ The short format includes a hash to ensure the name is unique database-wide.
758
+
759
+ *Mike Coutermarsh*
760
+
761
+ * Introduce a more stable and optimized Marshal serializer for Active Record models.
762
+
763
+ Can be enabled with `config.active_record.marshalling_format_version = 7.1`.
764
+
765
+ *Jean Boussier*
766
+
767
+ * Allow specifying where clauses with column-tuple syntax.
428
768
 
429
- *Tomoyuki Kai*
769
+ Querying through `#where` now accepts a new tuple-syntax which accepts, as
770
+ a key, an array of columns and, as a value, an array of corresponding tuples.
771
+ The key specifies a list of columns, while the value is an array of
772
+ ordered-tuples that conform to the column list.
430
773
 
431
- * Build predicate conditions with objects that delegate `#id` and primary key:
774
+ For instance:
432
775
 
433
776
  ```ruby
434
- class AdminAuthor
435
- delegate_missing_to :@author
777
+ # Cpk::Book => Cpk::Book(author_id: integer, number: integer, title: string, revision: integer)
778
+ # Cpk::Book.primary_key => ["author_id", "number"]
436
779
 
437
- def initialize(author)
438
- @author = author
439
- end
780
+ book = Cpk::Book.create!(author_id: 1, number: 1)
781
+ Cpk::Book.where(Cpk::Book.primary_key => [[1, 2]]) # => [book]
782
+
783
+ # Topic => Topic(id: integer, title: string, author_name: string...)
784
+
785
+ Topic.where([:title, :author_name] => [["The Alchemist", "Paulo Coelho"], ["Harry Potter", "J.K Rowling"]])
786
+ ```
787
+
788
+ *Paarth Madan*
789
+
790
+ * Allow warning codes to be ignore when reporting SQL warnings.
791
+
792
+ Active Record config that can ignore warning codes
793
+
794
+ ```ruby
795
+ # Configure allowlist of warnings that should always be ignored
796
+ config.active_record.db_warnings_ignore = [
797
+ "1062", # MySQL Error 1062: Duplicate entry
798
+ ]
799
+ ```
800
+
801
+ This is supported for the MySQL and PostgreSQL adapters.
802
+
803
+ *Nick Borromeo*
804
+
805
+ * Introduce `:active_record_fixtures` lazy load hook.
806
+
807
+ Hooks defined with this name will be run whenever `TestFixtures` is included
808
+ in a class.
809
+
810
+ ```ruby
811
+ ActiveSupport.on_load(:active_record_fixtures) do
812
+ self.fixture_paths << "test/fixtures"
440
813
  end
441
814
 
442
- Post.where(author: AdminAuthor.new(author))
815
+ klass = Class.new
816
+ klass.include(ActiveRecord::TestFixtures)
817
+
818
+ klass.fixture_paths # => ["test/fixtures"]
443
819
  ```
444
820
 
445
- *Sean Doyle*
821
+ *Andrew Novoselac*
446
822
 
447
- * Add `connected_to_many` API.
823
+ * Introduce `TestFixtures#fixture_paths`.
448
824
 
449
- This API allows applications to connect to multiple databases at once without switching all of them or implementing a deeply nested stack.
825
+ Multiple fixture paths can now be specified using the `#fixture_paths` accessor.
826
+ Apps will continue to have `test/fixtures` as their one fixture path by default,
827
+ but additional fixture paths can be specified.
450
828
 
451
- Before:
829
+ ```ruby
830
+ ActiveSupport::TestCase.fixture_paths << "component1/test/fixtures"
831
+ ActiveSupport::TestCase.fixture_paths << "component2/test/fixtures"
832
+ ```
452
833
 
453
- AnimalsRecord.connected_to(role: :reading) do
454
- MealsRecord.connected_to(role: :reading) do
455
- Dog.first # read from animals replica
456
- Dinner.first # read from meals replica
457
- Person.first # read from primary writer
458
- end
459
- end
834
+ `TestFixtures#fixture_path` is now deprecated.
460
835
 
461
- After:
836
+ *Andrew Novoselac*
462
837
 
463
- ActiveRecord::Base.connected_to_many([AnimalsRecord, MealsRecord], role: :reading) do
464
- Dog.first # read from animals replica
465
- Dinner.first # read from meals replica
466
- Person.first # read from primary writer
467
- end
838
+ * Adds support for deferrable exclude constraints in PostgreSQL.
468
839
 
469
- *Eileen M. Uchitelle*, *John Crepezzi*
840
+ By default, exclude constraints in PostgreSQL are checked after each statement.
841
+ This works for most use cases, but becomes a major limitation when replacing
842
+ records with overlapping ranges by using multiple statements.
470
843
 
471
- * Add option to raise or log for `ActiveRecord::StrictLoadingViolationError`.
844
+ ```ruby
845
+ exclusion_constraint :users, "daterange(valid_from, valid_to) WITH &&", deferrable: :immediate
846
+ ```
472
847
 
473
- Some applications may not want to raise an error in production if using `strict_loading`. This would allow an application to set strict loading to log for the production environment while still raising in development and test environments.
848
+ Passing `deferrable: :immediate` checks constraint after each statement,
849
+ but allows manually deferring the check using `SET CONSTRAINTS ALL DEFERRED`
850
+ within a transaction. This will cause the excludes to be checked after the transaction.
474
851
 
475
- Set `config.active_record.action_on_strict_loading_violation` to `:log` errors instead of raising.
852
+ It's also possible to change the default behavior from an immediate check
853
+ (after the statement), to a deferred check (after the transaction):
476
854
 
477
- *Eileen M. Uchitelle*
855
+ ```ruby
856
+ exclusion_constraint :users, "daterange(valid_from, valid_to) WITH &&", deferrable: :deferred
857
+ ```
478
858
 
479
- * Allow the inverse of a `has_one` association that was previously autosaved to be loaded.
859
+ *Hiroyuki Ishii*
480
860
 
481
- Fixes #34255.
861
+ * Respect `foreign_type` option to `delegated_type` for `{role}_class` method.
482
862
 
483
- *Steven Weber*
863
+ Usage of `delegated_type` with non-conventional `{role}_type` column names can now be specified with `foreign_type` option.
864
+ This option is the same as `foreign_type` as forwarded to the underlying `belongs_to` association that `delegated_type` wraps.
484
865
 
485
- * Optimise the length of index names for polymorphic references by using the reference name rather than the type and id column names.
866
+ *Jason Karns*
486
867
 
487
- Because the default behaviour when adding an index with multiple columns is to use all column names in the index name, this could frequently lead to overly long index names for polymorphic references which would fail the migration if it exceeded the database limit.
868
+ * Add support for unique constraints (PostgreSQL-only).
488
869
 
489
- This change reduces the chance of that happening by using the reference name, e.g. `index_my_table_on_my_reference`.
870
+ ```ruby
871
+ add_unique_key :sections, [:position], deferrable: :deferred, name: "unique_section_position"
872
+ remove_unique_key :sections, name: "unique_section_position"
873
+ ```
490
874
 
491
- Fixes #38655.
875
+ See PostgreSQL's [Unique Constraints](https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-UNIQUE-CONSTRAINTS) documentation for more on unique constraints.
492
876
 
493
- *Luke Redpath*
877
+ By default, unique constraints in PostgreSQL are checked after each statement.
878
+ This works for most use cases, but becomes a major limitation when replacing
879
+ records with unique column by using multiple statements.
494
880
 
495
- * MySQL: Uniqueness validator now respects default database collation,
496
- no longer enforce case sensitive comparison by default.
881
+ An example of swapping unique columns between records.
497
882
 
498
- *Ryuta Kamizono*
883
+ ```ruby
884
+ # position is unique column
885
+ old_item = Item.create!(position: 1)
886
+ new_item = Item.create!(position: 2)
887
+
888
+ Item.transaction do
889
+ old_item.update!(position: 2)
890
+ new_item.update!(position: 1)
891
+ end
892
+ ```
499
893
 
500
- * Remove deprecated methods from `ActiveRecord::ConnectionAdapters::DatabaseLimits`.
894
+ Using the default behavior, the transaction would fail when executing the
895
+ first `UPDATE` statement.
501
896
 
502
- `column_name_length`
503
- `table_name_length`
504
- `columns_per_table`
505
- `indexes_per_table`
506
- `columns_per_multicolumn_index`
507
- `sql_query_length`
508
- `joins_per_query`
897
+ By passing the `:deferrable` option to the `add_unique_key` statement in
898
+ migrations, it's possible to defer this check.
509
899
 
510
- *Rafael Mendonça França*
900
+ ```ruby
901
+ add_unique_key :items, [:position], deferrable: :immediate
902
+ ```
511
903
 
512
- * Remove deprecated `ActiveRecord::ConnectionAdapters::AbstractAdapter#supports_multi_insert?`.
904
+ Passing `deferrable: :immediate` does not change the behaviour of the previous example,
905
+ but allows manually deferring the check using `SET CONSTRAINTS ALL DEFERRED` within a transaction.
906
+ This will cause the unique constraints to be checked after the transaction.
513
907
 
514
- *Rafael Mendonça França*
908
+ It's also possible to adjust the default behavior from an immediate
909
+ check (after the statement), to a deferred check (after the transaction):
515
910
 
516
- * Remove deprecated `ActiveRecord::ConnectionAdapters::AbstractAdapter#supports_foreign_keys_in_create?`.
911
+ ```ruby
912
+ add_unique_key :items, [:position], deferrable: :deferred
913
+ ```
517
914
 
518
- *Rafael Mendonça França*
915
+ If you want to change an existing unique index to deferrable, you can use :using_index
916
+ to create deferrable unique constraints.
519
917
 
520
- * Remove deprecated `ActiveRecord::ConnectionAdapters::PostgreSQLAdapter#supports_ranges?`.
918
+ ```ruby
919
+ add_unique_key :items, deferrable: :deferred, using_index: "index_items_on_position"
920
+ ```
521
921
 
522
- *Rafael Mendonça França*
922
+ *Hiroyuki Ishii*
523
923
 
524
- * Remove deprecated `ActiveRecord::Base#update_attributes` and `ActiveRecord::Base#update_attributes!`.
924
+ * Remove deprecated `Tasks::DatabaseTasks.schema_file_type`.
525
925
 
526
926
  *Rafael Mendonça França*
527
927
 
528
- * Remove deprecated `migrations_path` argument in `ActiveRecord::ConnectionAdapter::SchemaStatements#assume_migrated_upto_version`.
928
+ * Remove deprecated `config.active_record.partial_writes`.
529
929
 
530
930
  *Rafael Mendonça França*
531
931
 
532
- * Remove deprecated `config.active_record.sqlite3.represent_boolean_as_integer`.
932
+ * Remove deprecated `ActiveRecord::Base` config accessors.
533
933
 
534
934
  *Rafael Mendonça França*
535
935
 
536
- * `relation.create` does no longer leak scope to class level querying methods
537
- in initialization block and callbacks.
936
+ * Remove the `:include_replicas` argument from `configs_for`. Use `:include_hidden` argument instead.
538
937
 
539
- Before:
938
+ *Eileen M. Uchitelle*
540
939
 
541
- User.where(name: "John").create do |john|
542
- User.find_by(name: "David") # => nil
543
- end
940
+ * Allow applications to lookup a config via a custom hash key.
544
941
 
545
- After:
942
+ 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.
546
943
 
547
- User.where(name: "John").create do |john|
548
- User.find_by(name: "David") # => #<User name: "David", ...>
549
- end
944
+ ```ruby
945
+ ActiveRecord::Base.configurations.configs_for(env_name: "development", name: "primary", config_key: :vitess)
946
+ ActiveRecord::Base.configurations.configs_for(env_name: "development", config_key: :vitess)
947
+ ```
550
948
 
551
- *Ryuta Kamizono*
949
+ *Eileen M. Uchitelle*
950
+
951
+ * Allow applications to register a custom database configuration handler.
952
+
953
+ 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`.
552
954
 
553
- * Named scope chain does no longer leak scope to class level querying methods.
955
+ Given the following database YAML we want the `animals` db to create a `CustomConfig` object instead while the `primary` database will be a `UrlConfig`:
554
956
 
555
- class User < ActiveRecord::Base
556
- scope :david, -> { User.where(name: "David") }
957
+ ```yaml
958
+ development:
959
+ primary:
960
+ url: postgres://localhost/primary
961
+ animals:
962
+ url: postgres://localhost/animals
963
+ custom_config:
964
+ sharded: 1
965
+ ```
966
+
967
+ To register a custom handler first make a class that has your custom methods:
968
+
969
+ ```ruby
970
+ class CustomConfig < ActiveRecord::DatabaseConfigurations::UrlConfig
971
+ def sharded?
972
+ custom_config.fetch("sharded", false)
973
+ end
974
+
975
+ private
976
+ def custom_config
977
+ configuration_hash.fetch(:custom_config)
557
978
  end
979
+ end
980
+ ```
558
981
 
559
- Before:
982
+ Then register the config in an initializer:
560
983
 
561
- User.where(name: "John").david
562
- # SELECT * FROM users WHERE name = 'John' AND name = 'David'
984
+ ```ruby
985
+ ActiveRecord::DatabaseConfigurations.register_db_config_handler do |env_name, name, url, config|
986
+ next unless config.key?(:custom_config)
987
+ CustomConfig.new(env_name, name, url, config)
988
+ end
989
+ ```
563
990
 
564
- After:
991
+ 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.
565
992
 
566
- User.where(name: "John").david
567
- # SELECT * FROM users WHERE name = 'David'
993
+ *Eileen M. Uchitelle and John Crepezzi*
568
994
 
569
- *Ryuta Kamizono*
995
+ * `ActiveRecord::Base.serialize` no longer uses YAML by default.
570
996
 
571
- * Remove deprecated methods from `ActiveRecord::DatabaseConfigurations`.
997
+ YAML isn't particularly performant and can lead to security issues
998
+ if not used carefully.
572
999
 
573
- `fetch`
574
- `each`
575
- `first`
576
- `values`
577
- `[]=`
1000
+ Unfortunately there isn't really any good serializers in Ruby's stdlib
1001
+ to replace it.
578
1002
 
579
- *Rafael Mendonça França*
1003
+ The obvious choice would be JSON, which is a fine format for this use case,
1004
+ however the JSON serializer in Ruby's stdlib isn't strict enough, as it fallback
1005
+ to casting unknown types to strings, which could lead to corrupted data.
580
1006
 
581
- * `where.not` now generates NAND predicates instead of NOR.
1007
+ Some third party JSON libraries like `Oj` have a suitable strict mode.
582
1008
 
583
- Before:
1009
+ So it's preferable that users choose a serializer based on their own constraints.
584
1010
 
585
- User.where.not(name: "Jon", role: "admin")
586
- # SELECT * FROM users WHERE name != 'Jon' AND role != 'admin'
1011
+ The original default can be restored by setting `config.active_record.default_column_serializer = YAML`.
587
1012
 
588
- After:
1013
+ *Jean Boussier*
589
1014
 
590
- User.where.not(name: "Jon", role: "admin")
591
- # SELECT * FROM users WHERE NOT (name == 'Jon' AND role == 'admin')
1015
+ * `ActiveRecord::Base.serialize` signature changed.
592
1016
 
593
- *Rafael Mendonça França*
1017
+ Rather than a single positional argument that accepts two possible
1018
+ types of values, `serialize` now accepts two distinct keyword arguments.
594
1019
 
595
- * Remove deprecated `ActiveRecord::Result#to_hash` method.
1020
+ Before:
596
1021
 
597
- *Rafael Mendonça França*
1022
+ ```ruby
1023
+ serialize :content, JSON
1024
+ serialize :backtrace, Array
1025
+ ```
598
1026
 
599
- * Deprecate `ActiveRecord::Base.allow_unsafe_raw_sql`.
1027
+ After:
600
1028
 
601
- *Rafael Mendonça França*
1029
+ ```ruby
1030
+ serialize :content, coder: JSON
1031
+ serialize :backtrace, type: Array
1032
+ ```
1033
+
1034
+ *Jean Boussier*
602
1035
 
603
- * Remove deprecated support for using unsafe raw SQL in `ActiveRecord::Relation` methods.
1036
+ * YAML columns use `YAML.safe_dump` if available.
604
1037
 
605
- *Rafael Mendonça França*
1038
+ As of `psych 5.1.0`, `YAML.safe_dump` can now apply the same permitted
1039
+ types restrictions than `YAML.safe_load`.
606
1040
 
607
- * Allow users to silence the "Rails couldn't infer whether you are using multiple databases..."
608
- message using `config.active_record.suppress_multiple_database_warning`.
1041
+ It's preferable to ensure the payload only use allowed types when we first
1042
+ try to serialize it, otherwise you may end up with invalid records in the
1043
+ database.
609
1044
 
610
- *Omri Gabay*
1045
+ *Jean Boussier*
611
1046
 
612
- * Connections can be granularly switched for abstract classes when `connected_to` is called.
1047
+ * `ActiveRecord::QueryLogs` better handle broken encoding.
613
1048
 
614
- This change allows `connected_to` to switch a `role` and/or `shard` for a single abstract class instead of all classes globally. Applications that want to use the new feature need to set `config.active_record.legacy_connection_handling` to `false` in their application configuration.
1049
+ It's not uncommon when building queries with BLOB fields to contain
1050
+ binary data. Unless the call carefully encode the string in ASCII-8BIT
1051
+ it generally end up being encoded in `UTF-8`, and `QueryLogs` would
1052
+ end up failing on it.
615
1053
 
616
- Example usage:
1054
+ `ActiveRecord::QueryLogs` no longer depend on the query to be properly encoded.
617
1055
 
618
- Given an application we have a `User` model that inherits from `ApplicationRecord` and a `Dog` model that inherits from `AnimalsRecord`. `AnimalsRecord` and `ApplicationRecord` have writing and reading connections as well as shard `default`, `one`, and `two`.
1056
+ *Jean Boussier*
619
1057
 
620
- ```ruby
621
- ActiveRecord::Base.connected_to(role: :reading) do
622
- User.first # reads from default replica
623
- Dog.first # reads from default replica
1058
+ * Fix a bug where `ActiveRecord::Generators::ModelGenerator` would not respect create_table_migration template overrides.
624
1059
 
625
- AnimalsRecord.connected_to(role: :writing, shard: :one) do
626
- User.first # reads from default replica
627
- Dog.first # reads from shard one primary
628
- end
1060
+ ```
1061
+ rails g model create_books title:string content:text
1062
+ ```
1063
+ will now read from the create_table_migration.rb.tt template in the following locations in order:
1064
+ ```
1065
+ lib/templates/active_record/model/create_table_migration.rb
1066
+ lib/templates/active_record/migration/create_table_migration.rb
1067
+ ```
629
1068
 
630
- User.first # reads from default replica
631
- Dog.first # reads from default replica
1069
+ *Spencer Neste*
632
1070
 
633
- ApplicationRecord.connected_to(role: :writing, shard: :two) do
634
- User.first # reads from shard two primary
635
- Dog.first # reads from default replica
636
- end
637
- end
1071
+ * `ActiveRecord::Relation#explain` now accepts options.
1072
+
1073
+ For databases and adapters which support them (currently PostgreSQL
1074
+ and MySQL), options can be passed to `explain` to provide more
1075
+ detailed query plan analysis:
1076
+
1077
+ ```ruby
1078
+ Customer.where(id: 1).joins(:orders).explain(:analyze, :verbose)
638
1079
  ```
639
1080
 
640
- *Eileen M. Uchitelle*, *John Crepezzi*
1081
+ *Reid Lynch*
641
1082
 
642
- * Allow double-dash comment syntax when querying read-only databases
1083
+ * Multiple `Arel::Nodes::SqlLiteral` nodes can now be added together to
1084
+ form `Arel::Nodes::Fragments` nodes. This allows joining several pieces
1085
+ of SQL.
643
1086
 
644
- *James Adam*
1087
+ *Matthew Draper*, *Ole Friis*
645
1088
 
646
- * Add `values_at` method.
1089
+ * `ActiveRecord::Base#signed_id` raises if called on a new record.
1090
+
1091
+ Previously it would return an ID that was not usable, since it was based on `id = nil`.
1092
+
1093
+ *Alex Ghiculescu*
647
1094
 
648
- Returns an array containing the values associated with the given methods.
1095
+ * Allow SQL warnings to be reported.
1096
+
1097
+ Active Record configs can be set to enable SQL warning reporting.
649
1098
 
650
1099
  ```ruby
651
- topic = Topic.first
652
- topic.values_at(:title, :author_name)
653
- # => ["Budget", "Jason"]
1100
+ # Configure action to take when SQL query produces warning
1101
+ config.active_record.db_warnings_action = :raise
1102
+
1103
+ # Configure allowlist of warnings that should always be ignored
1104
+ config.active_record.db_warnings_ignore = [
1105
+ /Invalid utf8mb4 character string/,
1106
+ "An exact warning message",
1107
+ ]
654
1108
  ```
655
1109
 
656
- Similar to `Hash#values_at` but on an Active Record instance.
657
-
658
- *Guillaume Briday*
1110
+ This is supported for the MySQL and PostgreSQL adapters.
659
1111
 
660
- * Fix `read_attribute_before_type_cast` to consider attribute aliases.
1112
+ *Adrianna Chang*, *Paarth Madan*
661
1113
 
662
- *Marcelo Lauxen*
1114
+ * Add `#regroup` query method as a short-hand for `.unscope(:group).group(fields)`
663
1115
 
664
- * Support passing record to uniqueness validator `:conditions` callable:
1116
+ Example:
665
1117
 
666
1118
  ```ruby
667
- class Article < ApplicationRecord
668
- validates_uniqueness_of :title, conditions: ->(article) {
669
- published_at = article.published_at
670
- where(published_at: published_at.beginning_of_year..published_at.end_of_year)
671
- }
672
- end
1119
+ Post.group(:title).regroup(:author)
1120
+ # SELECT `posts`.`*` FROM `posts` GROUP BY `posts`.`author`
673
1121
  ```
674
1122
 
675
- *Eliot Sykes*
1123
+ *Danielius Visockas*
676
1124
 
677
- * `BatchEnumerator#update_all` and `BatchEnumerator#delete_all` now return the
678
- total number of rows affected, just like their non-batched counterparts.
1125
+ * PostgreSQL adapter method `enable_extension` now allows parameter to be `[schema_name.]<extension_name>`
1126
+ if the extension must be installed on another schema.
1127
+
1128
+ Example: `enable_extension('heroku_ext.hstore')`
1129
+
1130
+ *Leonardo Luarte*
1131
+
1132
+ * Add `:include` option to `add_index`.
1133
+
1134
+ Add support for including non-key columns in indexes for PostgreSQL
1135
+ with the `INCLUDE` parameter.
679
1136
 
680
1137
  ```ruby
681
- Person.in_batches.update_all("first_name = 'Eugene'") # => 42
682
- Person.in_batches.delete_all # => 42
1138
+ add_index(:users, :email, include: [:id, :created_at])
683
1139
  ```
684
1140
 
685
- Fixes #40287.
1141
+ will result in:
1142
+
1143
+ ```sql
1144
+ CREATE INDEX index_users_on_email USING btree (email) INCLUDE (id, created_at)
1145
+ ```
1146
+
1147
+ *Steve Abrams*
1148
+
1149
+ * `ActiveRecord::Relation`’s `#any?`, `#none?`, and `#one?` methods take an optional pattern
1150
+ argument, more closely matching their `Enumerable` equivalents.
1151
+
1152
+ *George Claghorn*
1153
+
1154
+ * Add `ActiveRecord::Base.normalizes` for declaring attribute normalizations.
1155
+
1156
+ An attribute normalization is applied when the attribute is assigned or
1157
+ updated, and the normalized value will be persisted to the database. The
1158
+ normalization is also applied to the corresponding keyword argument of query
1159
+ methods, allowing records to be queried using unnormalized values.
1160
+
1161
+ For example:
1162
+
1163
+ ```ruby
1164
+ class User < ActiveRecord::Base
1165
+ normalizes :email, with: -> email { email.strip.downcase }
1166
+ normalizes :phone, with: -> phone { phone.delete("^0-9").delete_prefix("1") }
1167
+ end
1168
+
1169
+ user = User.create(email: " CRUISE-CONTROL@EXAMPLE.COM\n")
1170
+ user.email # => "cruise-control@example.com"
1171
+
1172
+ user = User.find_by(email: "\tCRUISE-CONTROL@EXAMPLE.COM ")
1173
+ user.email # => "cruise-control@example.com"
1174
+ user.email_before_type_cast # => "cruise-control@example.com"
686
1175
 
687
- *Eugene Kenny*
1176
+ User.where(email: "\tCRUISE-CONTROL@EXAMPLE.COM ").count # => 1
1177
+ User.where(["email = ?", "\tCRUISE-CONTROL@EXAMPLE.COM "]).count # => 0
688
1178
 
689
- * Add support for PostgreSQL `interval` data type with conversion to
690
- `ActiveSupport::Duration` when loading records from database and
691
- serialization to ISO 8601 formatted duration string on save.
692
- Add support to define a column in migrations and get it in a schema dump.
693
- Optional column precision is supported.
1179
+ User.exists?(email: "\tCRUISE-CONTROL@EXAMPLE.COM ") # => true
1180
+ User.exists?(["email = ?", "\tCRUISE-CONTROL@EXAMPLE.COM "]) # => false
694
1181
 
695
- To use this in 6.1, you need to place the next string to your model file:
1182
+ User.normalize_value_for(:phone, "+1 (555) 867-5309") # => "5558675309"
1183
+ ```
696
1184
 
697
- attribute :duration, :interval
1185
+ *Jonathan Hefner*
698
1186
 
699
- To keep old behavior until 7.0 is released:
1187
+ * Hide changes to before_committed! callback behaviour behind flag.
700
1188
 
701
- attribute :duration, :string
1189
+ In #46525, behavior around before_committed! callbacks was changed so that callbacks
1190
+ would run on every enrolled record in a transaction, not just the first copy of a record.
1191
+ This change in behavior is now controlled by a configuration option,
1192
+ `config.active_record.before_committed_on_all_records`. It will be enabled by default on Rails 7.1.
702
1193
 
703
- Example:
1194
+ *Adrianna Chang*
704
1195
 
705
- create_table :events do |t|
706
- t.string :name
707
- t.interval :duration
708
- end
1196
+ * The `namespaced_controller` Query Log tag now matches the `controller` format
709
1197
 
710
- class Event < ApplicationRecord
711
- attribute :duration, :interval
712
- end
1198
+ For example, a request processed by `NameSpaced::UsersController` will now log as:
1199
+
1200
+ ```
1201
+ :controller # "users"
1202
+ :namespaced_controller # "name_spaced/users"
1203
+ ```
713
1204
 
714
- Event.create!(name: 'Rock Fest', duration: 2.days)
715
- Event.last.duration # => 2 days
716
- Event.last.duration.iso8601 # => "P2D"
717
- Event.new(duration: 'P1DT12H3S').duration # => 1 day, 12 hours, and 3 seconds
718
- Event.new(duration: '1 day') # Unknown value will be ignored and NULL will be written to database
1205
+ *Alex Ghiculescu*
719
1206
 
720
- *Andrey Novikov*
1207
+ * Return only unique ids from ActiveRecord::Calculations#ids
721
1208
 
722
- * Allow associations supporting the `dependent:` key to take `dependent: :destroy_async`.
1209
+ Updated ActiveRecord::Calculations#ids to only return the unique ids of the base model
1210
+ when using eager_load, preload and includes.
723
1211
 
724
1212
  ```ruby
725
- class Account < ActiveRecord::Base
726
- belongs_to :supplier, dependent: :destroy_async
727
- end
1213
+ Post.find_by(id: 1).comments.count
1214
+ # => 5
1215
+ Post.includes(:comments).where(id: 1).pluck(:id)
1216
+ # => [1, 1, 1, 1, 1]
1217
+ Post.includes(:comments).where(id: 1).ids
1218
+ # => [1]
728
1219
  ```
729
1220
 
730
- `:destroy_async` will enqueue a job to destroy associated records in the background.
1221
+ *Joshua Young*
731
1222
 
732
- *DHH*, *George Claghorn*, *Cory Gwin*, *Rafael Mendonça França*, *Adrianna Chang*
1223
+ * Stop using `LOWER()` for case-insensitive queries on `citext` columns
733
1224
 
734
- * Add `SKIP_TEST_DATABASE` environment variable to disable modifying the test database when `rails db:create` and `rails db:drop` are called.
1225
+ Previously, `LOWER()` was added for e.g. uniqueness validations with
1226
+ `case_sensitive: false`.
1227
+ It wasn't mentioned in the documentation that the index without `LOWER()`
1228
+ wouldn't be used in this case.
735
1229
 
736
- *Jason Schweier*
1230
+ *Phil Pirozhkov*
737
1231
 
738
- * `connects_to` can only be called on `ActiveRecord::Base` or abstract classes.
1232
+ * Extract `#sync_timezone_changes` method in AbstractMysqlAdapter to enable subclasses
1233
+ to sync database timezone changes without overriding `#raw_execute`.
739
1234
 
740
- Ensure that `connects_to` can only be called from `ActiveRecord::Base` or abstract classes. This protects the application from opening duplicate or too many connections.
1235
+ *Adrianna Chang*, *Paarth Madan*
741
1236
 
742
- *Eileen M. Uchitelle*, *John Crepezzi*
1237
+ * Do not write additional new lines when dumping sql migration versions
743
1238
 
744
- * All connection adapters `execute` now raises `ActiveRecord::ConnectionNotEstablished` rather than
745
- `ActiveRecord::StatementInvalid` when they encounter a connection error.
1239
+ 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.
746
1240
 
747
- *Jean Boussier*
1241
+ *Misha Schwartz*
748
1242
 
749
- * `Mysql2Adapter#quote_string` now raises `ActiveRecord::ConnectionNotEstablished` rather than
750
- `ActiveRecord::StatementInvalid` when it can't connect to the MySQL server.
1243
+ * Fix `composed_of` value freezing and duplication.
751
1244
 
752
- *Jean Boussier*
1245
+ Previously composite values exhibited two confusing behaviors:
753
1246
 
754
- * Add support for check constraints that are `NOT VALID` via `validate: false` (PostgreSQL-only).
1247
+ - When reading a compositve value it'd _NOT_ be frozen, allowing it to get out of sync with its underlying database
1248
+ columns.
1249
+ - When writing a compositve value the argument would be frozen, potentially confusing the caller.
755
1250
 
756
- *Alex Robbin*
1251
+ Currently, composite values instantiated based on database columns are frozen (addressing the first issue) and
1252
+ assigned compositve values are duplicated and the duplicate is frozen (addressing the second issue).
757
1253
 
758
- * Ensure the default configuration is considered primary or first for an environment
1254
+ *Greg Navis*
759
1255
 
760
- If a multiple database application provides a configuration named primary, that will be treated as default. In applications that do not have a primary entry, the default database configuration will be the first configuration for an environment.
1256
+ * Fix redundant updates to the column insensitivity cache
761
1257
 
762
- *Eileen M. Uchitelle*
1258
+ Fixed redundant queries checking column capability for insensitive
1259
+ comparison.
763
1260
 
764
- * Allow `where` references association names as joined table name aliases.
1261
+ *Phil Pirozhkov*
765
1262
 
766
- ```ruby
767
- class Comment < ActiveRecord::Base
768
- enum label: [:default, :child]
769
- has_many :children, class_name: "Comment", foreign_key: :parent_id
770
- end
1263
+ * Allow disabling methods generated by `ActiveRecord.enum`.
771
1264
 
772
- # ... FROM comments LEFT OUTER JOIN comments children ON ... WHERE children.label = 1
773
- Comment.includes(:children).where("children.label": "child")
774
- ```
1265
+ *Alfred Dominic*
775
1266
 
776
- *Ryuta Kamizono*
1267
+ * Avoid validating `belongs_to` association if it has not changed.
777
1268
 
778
- * Support storing demodulized class name for polymorphic type.
1269
+ Previously, when updating a record, Active Record will perform an extra query to check for the presence of
1270
+ `belongs_to` associations (if the presence is configured to be mandatory), even if that attribute hasn't changed.
779
1271
 
780
- Before Rails 6.1, storing demodulized class name is supported only for STI type
781
- by `store_full_sti_class` class attribute.
1272
+ Currently, only `belongs_to`-related columns are checked for presence. It is possible to have orphaned records with
1273
+ this approach. To avoid this problem, you need to use a foreign key.
782
1274
 
783
- Now `store_full_class_name` class attribute can handle both STI and polymorphic types.
1275
+ This behavior can be controlled by configuration:
784
1276
 
785
- *Ryuta Kamizono*
1277
+ ```ruby
1278
+ config.active_record.belongs_to_required_validates_foreign_key = false
1279
+ ```
786
1280
 
787
- * Deprecate `rails db:structure:{load, dump}` tasks and extend
788
- `rails db:schema:{load, dump}` tasks to work with either `:ruby` or `:sql` format,
789
- depending on `config.active_record.schema_format` configuration value.
1281
+ and will be disabled by default with `config.load_defaults 7.1`.
790
1282
 
791
1283
  *fatkodima*
792
1284
 
793
- * Respect the `select` values for eager loading.
1285
+ * `has_one` and `belongs_to` associations now define a `reset_association` method
1286
+ on the owner model (where `association` is the name of the association). This
1287
+ method unloads the cached associate record, if any, and causes the next access
1288
+ to query it from the database.
794
1289
 
795
- ```ruby
796
- post = Post.select("UPPER(title) AS title").first
797
- post.title # => "WELCOME TO THE WEBLOG"
798
- post.body # => ActiveModel::MissingAttributeError
1290
+ *George Claghorn*
799
1291
 
800
- # Rails 6.0 (ignore the `select` values)
801
- post = Post.select("UPPER(title) AS title").eager_load(:comments).first
802
- post.title # => "Welcome to the weblog"
803
- post.body # => "Such a lovely day"
1292
+ * Allow per attribute setting of YAML permitted classes (safe load) and unsafe load.
804
1293
 
805
- # Rails 6.1 (respect the `select` values)
806
- post = Post.select("UPPER(title) AS title").eager_load(:comments).first
807
- post.title # => "WELCOME TO THE WEBLOG"
808
- post.body # => ActiveModel::MissingAttributeError
809
- ```
1294
+ *Carlos Palhares*
810
1295
 
811
- *Ryuta Kamizono*
1296
+ * Add a build persistence method
1297
+
1298
+ Provides a wrapper for `new`, to provide feature parity with `create`s
1299
+ ability to create multiple records from an array of hashes, using the
1300
+ same notation as the `build` method on associations.
1301
+
1302
+ *Sean Denny*
812
1303
 
813
- * Allow attribute's default to be configured but keeping its own type.
1304
+ * Raise on assignment to readonly attributes
814
1305
 
815
1306
  ```ruby
816
1307
  class Post < ActiveRecord::Base
817
- attribute :written_at, default: -> { Time.now.utc }
1308
+ attr_readonly :content
818
1309
  end
819
-
820
- # Rails 6.0
821
- Post.type_for_attribute(:written_at) # => #<Type::Value ... precision: nil, ...>
822
-
823
- # Rails 6.1
824
- Post.type_for_attribute(:written_at) # => #<Type::DateTime ... precision: 6, ...>
1310
+ Post.create!(content: "cannot be updated")
1311
+ post.content # "cannot be updated"
1312
+ post.content = "something else" # => ActiveRecord::ReadonlyAttributeError
825
1313
  ```
826
1314
 
827
- *Ryuta Kamizono*
1315
+ Previously, assignment would succeed but silently not write to the database.
828
1316
 
829
- * Allow default to be configured for Enum.
1317
+ This behavior can be controlled by configuration:
830
1318
 
831
1319
  ```ruby
832
- class Book < ActiveRecord::Base
833
- enum status: [:proposed, :written, :published], _default: :published
834
- end
835
-
836
- Book.new.status # => "published"
1320
+ config.active_record.raise_on_assign_to_attr_readonly = true
837
1321
  ```
838
1322
 
839
- *Ryuta Kamizono*
1323
+ and will be enabled by default with `config.load_defaults 7.1`.
840
1324
 
841
- * Deprecate YAML loading from legacy format older than Rails 5.0.
1325
+ *Alex Ghiculescu*, *Hartley McGuire*
842
1326
 
843
- *Ryuta Kamizono*
1327
+ * Allow unscoping of preload and eager_load associations
844
1328
 
845
- * Added the setting `ActiveRecord::Base.immutable_strings_by_default`, which
846
- allows you to specify that all string columns should be frozen unless
847
- otherwise specified. This will reduce memory pressure for applications which
848
- do not generally mutate string properties of Active Record objects.
1329
+ Added the ability to unscope preload and eager_load associations just like
1330
+ includes, joins, etc. See ActiveRecord::QueryMethods::VALID_UNSCOPING_VALUES
1331
+ for the full list of supported unscopable scopes.
849
1332
 
850
- *Sean Griffin*, *Ryuta Kamizono*
1333
+ ```ruby
1334
+ query.unscope(:eager_load, :preload).group(:id).select(:id)
1335
+ ```
851
1336
 
852
- * Deprecate `map!` and `collect!` on `ActiveRecord::Result`.
1337
+ *David Morehouse*
853
1338
 
854
- *Ryuta Kamizono*
1339
+ * Add automatic filtering of encrypted attributes on inspect
855
1340
 
856
- * Support `relation.and` for intersection as Set theory.
1341
+ This feature is enabled by default but can be disabled with
857
1342
 
858
1343
  ```ruby
859
- david_and_mary = Author.where(id: [david, mary])
860
- mary_and_bob = Author.where(id: [mary, bob])
861
-
862
- david_and_mary.merge(mary_and_bob) # => [mary, bob]
863
-
864
- david_and_mary.and(mary_and_bob) # => [mary]
865
- david_and_mary.or(mary_and_bob) # => [david, mary, bob]
1344
+ config.active_record.encryption.add_to_filter_parameters = false
866
1345
  ```
867
1346
 
868
- *Ryuta Kamizono*
869
-
870
- * Merging conditions on the same column no longer maintain both conditions,
871
- and will be consistently replaced by the latter condition in Rails 7.0.
872
- To migrate to Rails 7.0's behavior, use `relation.merge(other, rewhere: true)`.
873
-
874
- ```ruby
875
- # Rails 6.1 (IN clause is replaced by merger side equality condition)
876
- Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob]
1347
+ *Hartley McGuire*
877
1348
 
878
- # Rails 6.1 (both conflict conditions exists, deprecated)
879
- Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => []
1349
+ * Clear locking column on #dup
880
1350
 
881
- # Rails 6.1 with rewhere to migrate to Rails 7.0's behavior
882
- Author.where(id: david.id..mary.id).merge(Author.where(id: bob), rewhere: true) # => [bob]
1351
+ This change fixes not to duplicate locking_column like id and timestamps.
883
1352
 
884
- # Rails 7.0 (same behavior with IN clause, mergee side condition is consistently replaced)
885
- Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob]
886
- Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => [bob]
1353
+ ```
1354
+ car = Car.create!
1355
+ car.touch
1356
+ car.lock_version #=> 1
1357
+ car.dup.lock_version #=> 0
887
1358
  ```
888
1359
 
889
- *Ryuta Kamizono*
1360
+ *Shouichi Kamiya*, *Seonggi Yang*, *Ryohei UEDA*
890
1361
 
891
- * Do not mark Postgresql MAC address and UUID attributes as changed when the assigned value only varies by case.
1362
+ * Invalidate transaction as early as possible
892
1363
 
893
- *Peter Fry*
1364
+ After rescuing a `TransactionRollbackError` exception Rails invalidates transactions earlier in the flow
1365
+ allowing the framework to skip issuing the `ROLLBACK` statement in more cases.
1366
+ Only affects adapters that have `savepoint_errors_invalidate_transactions?` configured as `true`,
1367
+ which at this point is only applicable to the `mysql2` adapter.
894
1368
 
895
- * Resolve issue with insert_all unique_by option when used with expression index.
1369
+ *Nikita Vasilevsky*
896
1370
 
897
- When the `:unique_by` option of `ActiveRecord::Persistence.insert_all` and
898
- `ActiveRecord::Persistence.upsert_all` was used with the name of an expression index, an error
899
- was raised. Adding a guard around the formatting behavior for the `:unique_by` corrects this.
1371
+ * Allow configuring columns list to be used in SQL queries issued by an `ActiveRecord::Base` object
900
1372
 
901
- Usage:
1373
+ It is now possible to configure columns list that will be used to build an SQL query clauses when
1374
+ updating, deleting or reloading an `ActiveRecord::Base` object
902
1375
 
903
1376
  ```ruby
904
- create_table :books, id: :integer, force: true do |t|
905
- t.column :name, :string
906
- t.index "lower(name)", unique: true
1377
+ class Developer < ActiveRecord::Base
1378
+ query_constraints :company_id, :id
907
1379
  end
908
-
909
- Book.insert_all [{ name: "MyTest" }], unique_by: :index_books_on_lower_name
1380
+ developer = Developer.first.update(name: "Bob")
1381
+ # => UPDATE "developers" SET "name" = 'Bob' WHERE "developers"."company_id" = 1 AND "developers"."id" = 1
910
1382
  ```
911
1383
 
912
- Fixes #39516.
1384
+ *Nikita Vasilevsky*
913
1385
 
914
- *Austen Madden*
1386
+ * Adds `validate` to foreign keys and check constraints in schema.rb
915
1387
 
916
- * Add basic support for CHECK constraints to database migrations.
1388
+ Previously, `schema.rb` would not record if `validate: false` had been used when adding a foreign key or check
1389
+ constraint, so restoring a database from the schema could result in foreign keys or check constraints being
1390
+ incorrectly validated.
917
1391
 
918
- Usage:
1392
+ *Tommy Graves*
919
1393
 
920
- ```ruby
921
- add_check_constraint :products, "price > 0", name: "price_check"
922
- remove_check_constraint :products, name: "price_check"
923
- ```
1394
+ * Adapter `#execute` methods now accept an `allow_retry` option. When set to `true`, the SQL statement will be
1395
+ retried, up to the database's configured `connection_retries` value, upon encountering connection-related errors.
924
1396
 
925
- *fatkodima*
1397
+ *Adrianna Chang*
926
1398
 
927
- * Add `ActiveRecord::Base.strict_loading_by_default` and `ActiveRecord::Base.strict_loading_by_default=`
928
- to enable/disable strict_loading mode by default for a model. The configuration's value is
929
- inheritable by subclasses, but they can override that value and it will not impact parent class.
1399
+ * Only trigger `after_commit :destroy` callbacks when a database row is deleted.
930
1400
 
931
- Usage:
1401
+ This prevents `after_commit :destroy` callbacks from being triggered again
1402
+ when `destroy` is called multiple times on the same record.
932
1403
 
933
- ```ruby
934
- class Developer < ApplicationRecord
935
- self.strict_loading_by_default = true
1404
+ *Ben Sheldon*
936
1405
 
937
- has_many :projects
938
- end
1406
+ * Fix `ciphertext_for` for yet-to-be-encrypted values.
939
1407
 
940
- dev = Developer.first
941
- dev.projects.first
942
- # => ActiveRecord::StrictLoadingViolationError Exception: Developer is marked as strict_loading and Project cannot be lazily loaded.
943
- ```
1408
+ Previously, `ciphertext_for` returned the cleartext of values that had not
1409
+ yet been encrypted, such as with an unpersisted record:
944
1410
 
945
- *bogdanvlviv*
1411
+ ```ruby
1412
+ Post.encrypts :body
946
1413
 
947
- * Deprecate passing an Active Record object to `quote`/`type_cast` directly.
1414
+ post = Post.create!(body: "Hello")
1415
+ post.ciphertext_for(:body)
1416
+ # => "{\"p\":\"abc..."
948
1417
 
949
- *Ryuta Kamizono*
1418
+ post.body = "World"
1419
+ post.ciphertext_for(:body)
1420
+ # => "World"
1421
+ ```
950
1422
 
951
- * Default engine `ENGINE=InnoDB` is no longer dumped to make schema more agnostic.
1423
+ Now, `ciphertext_for` will always return the ciphertext of encrypted
1424
+ attributes:
952
1425
 
953
- Before:
1426
+ ```ruby
1427
+ Post.encrypts :body
954
1428
 
955
- ```ruby
956
- create_table "accounts", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci", force: :cascade do |t|
957
- end
958
- ```
1429
+ post = Post.create!(body: "Hello")
1430
+ post.ciphertext_for(:body)
1431
+ # => "{\"p\":\"abc..."
959
1432
 
960
- After:
1433
+ post.body = "World"
1434
+ post.ciphertext_for(:body)
1435
+ # => "{\"p\":\"xyz..."
1436
+ ```
961
1437
 
962
- ```ruby
963
- create_table "accounts", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
964
- end
965
- ```
1438
+ *Jonathan Hefner*
966
1439
 
967
- *Ryuta Kamizono*
1440
+ * Fix a bug where using groups and counts with long table names would return incorrect results.
968
1441
 
969
- * Added delegated type as an alternative to single-table inheritance for representing class hierarchies.
970
- See ActiveRecord::DelegatedType for the full description.
1442
+ *Shota Toguchi*, *Yusaku Ono*
971
1443
 
972
- *DHH*
1444
+ * Fix encryption of column default values.
973
1445
 
974
- * Deprecate aggregations with group by duplicated fields.
1446
+ Previously, encrypted attributes that used column default values appeared to
1447
+ be encrypted on create, but were not:
975
1448
 
976
- To migrate to Rails 7.0's behavior, use `uniq!(:group)` to deduplicate group fields.
1449
+ ```ruby
1450
+ Book.encrypts :name
977
1451
 
978
- ```ruby
979
- accounts = Account.group(:firm_id)
1452
+ book = Book.create!
1453
+ book.name
1454
+ # => "<untitled>"
1455
+ book.name_before_type_cast
1456
+ # => "{\"p\":\"abc..."
1457
+ book.reload.name_before_type_cast
1458
+ # => "<untitled>"
1459
+ ```
980
1460
 
981
- # duplicated group fields, deprecated.
982
- accounts.merge(accounts.where.not(credit_limit: nil)).sum(:credit_limit)
983
- # => {
984
- # [1, 1] => 50,
985
- # [2, 2] => 60
986
- # }
1461
+ Now, attributes with column default values are encrypted:
987
1462
 
988
- # use `uniq!(:group)` to deduplicate group fields.
989
- accounts.merge(accounts.where.not(credit_limit: nil)).uniq!(:group).sum(:credit_limit)
990
- # => {
991
- # 1 => 50,
992
- # 2 => 60
993
- # }
994
- ```
1463
+ ```ruby
1464
+ Book.encrypts :name
995
1465
 
996
- *Ryuta Kamizono*
1466
+ book = Book.create!
1467
+ book.name
1468
+ # => "<untitled>"
1469
+ book.name_before_type_cast
1470
+ # => "{\"p\":\"abc..."
1471
+ book.reload.name_before_type_cast
1472
+ # => "{\"p\":\"abc..."
1473
+ ```
997
1474
 
998
- * Deprecate duplicated query annotations.
1475
+ *Jonathan Hefner*
999
1476
 
1000
- To migrate to Rails 7.0's behavior, use `uniq!(:annotate)` to deduplicate query annotations.
1477
+ * Deprecate delegation from `Base` to `connection_handler`.
1001
1478
 
1002
- ```ruby
1003
- accounts = Account.where(id: [1, 2]).annotate("david and mary")
1479
+ 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.
1004
1480
 
1005
- # duplicated annotations, deprecated.
1006
- accounts.merge(accounts.rewhere(id: 3))
1007
- # SELECT accounts.* FROM accounts WHERE accounts.id = 3 /* david and mary */ /* david and mary */
1481
+ *Eileen M. Uchitelle*
1008
1482
 
1009
- # use `uniq!(:annotate)` to deduplicate annotations.
1010
- accounts.merge(accounts.rewhere(id: 3)).uniq!(:annotate)
1011
- # SELECT accounts.* FROM accounts WHERE accounts.id = 3 /* david and mary */
1012
- ```
1483
+ * Allow ActiveRecord::QueryMethods#reselect to receive hash values, similar to ActiveRecord::QueryMethods#select
1013
1484
 
1014
- *Ryuta Kamizono*
1485
+ *Sampat Badhe*
1015
1486
 
1016
- * Resolve conflict between counter cache and optimistic locking.
1487
+ * Validate options when managing columns and tables in migrations.
1017
1488
 
1018
- Bump an Active Record instance's lock version after updating its counter
1019
- cache. This avoids raising an unnecessary `ActiveRecord::StaleObjectError`
1020
- upon subsequent transactions by maintaining parity with the corresponding
1021
- database record's `lock_version` column.
1489
+ If an invalid option is passed to a migration method like `create_table` and `add_column`, an error will be raised
1490
+ instead of the option being silently ignored. Validation of the options will only be applied for new migrations
1491
+ that are created.
1022
1492
 
1023
- Fixes #16449.
1493
+ *Guo Xiang Tan*, *George Wambold*
1024
1494
 
1025
- *Aaron Lipman*
1495
+ * 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)
1026
1496
 
1027
- * Support merging option `:rewhere` to allow mergee side condition to be replaced exactly.
1497
+ 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`.
1028
1498
 
1029
- ```ruby
1030
- david_and_mary = Author.where(id: david.id..mary.id)
1499
+ *Modulitos* and *Iheanyi*
1031
1500
 
1032
- # both conflict conditions exists
1033
- david_and_mary.merge(Author.where(id: bob)) # => []
1501
+ * Allow any ERB in the database.yml when creating rake tasks.
1034
1502
 
1035
- # mergee side condition is replaced by rewhere
1036
- david_and_mary.merge(Author.rewhere(id: bob)) # => [bob]
1503
+ Any ERB can be used in `database.yml` even if it accesses environment
1504
+ configurations.
1037
1505
 
1038
- # mergee side condition is replaced by rewhere option
1039
- david_and_mary.merge(Author.where(id: bob), rewhere: true) # => [bob]
1040
- ```
1506
+ Deprecates `config.active_record.suppress_multiple_database_warning`.
1041
1507
 
1042
- *Ryuta Kamizono*
1508
+ *Eike Send*
1043
1509
 
1044
- * Add support for finding records based on signed ids, which are tamper-proof, verified ids that can be
1045
- set to expire and scoped with a purpose. This is particularly useful for things like password reset
1046
- or email verification, where you want the bearer of the signed id to be able to interact with the
1047
- underlying record, but usually only within a certain time period.
1510
+ * Add table to error for duplicate column definitions.
1048
1511
 
1049
- ```ruby
1050
- signed_id = User.first.signed_id expires_in: 15.minutes, purpose: :password_reset
1512
+ If a migration defines duplicate columns for a table, the error message
1513
+ shows which table it concerns.
1051
1514
 
1052
- User.find_signed signed_id # => nil, since the purpose does not match
1515
+ *Petrik de Heus*
1053
1516
 
1054
- travel 16.minutes
1055
- User.find_signed signed_id, purpose: :password_reset # => nil, since the signed id has expired
1517
+ * Fix erroneous nil default precision on virtual datetime columns.
1056
1518
 
1057
- travel_back
1058
- User.find_signed signed_id, purpose: :password_reset # => User.first
1519
+ Prior to this change, virtual datetime columns did not have the same
1520
+ default precision as regular datetime columns, resulting in the following
1521
+ being erroneously equivalent:
1059
1522
 
1060
- User.find_signed! "bad data" # => ActiveSupport::MessageVerifier::InvalidSignature
1061
- ```
1523
+ t.virtual :name, type: datetime, as: "expression"
1524
+ t.virtual :name, type: datetime, precision: nil, as: "expression"
1062
1525
 
1063
- *DHH*
1526
+ This change fixes the default precision lookup, so virtual and regular
1527
+ datetime column default precisions match.
1064
1528
 
1065
- * Support `ALGORITHM = INSTANT` DDL option for index operations on MySQL.
1529
+ *Sam Bostock*
1066
1530
 
1067
- *Ryuta Kamizono*
1531
+ * Use connection from `#with_raw_connection` in `#quote_string`.
1068
1532
 
1069
- * Fix index creation to preserve index comment in bulk change table on MySQL.
1533
+ This ensures that the string quoting is wrapped in the reconnect and retry logic
1534
+ that `#with_raw_connection` offers.
1070
1535
 
1071
- *Ryuta Kamizono*
1536
+ *Adrianna Chang*
1072
1537
 
1073
- * Allow `unscope` to be aware of table name qualified values.
1538
+ * Add `expires_at` option to `signed_id`.
1074
1539
 
1075
- It is possible to unscope only the column in the specified table.
1540
+ *Shouichi Kamiya*
1076
1541
 
1077
- ```ruby
1078
- posts = Post.joins(:comments).group(:"posts.hidden")
1079
- posts = posts.where("posts.hidden": false, "comments.hidden": false)
1542
+ * Allow applications to set retry deadline for query retries.
1080
1543
 
1081
- posts.count
1082
- # => { false => 10 }
1544
+ Building on the work done in #44576 and #44591, we extend the logic that automatically
1545
+ reconnects database connections to take into account a timeout limit. We won't retry
1546
+ a query if a given amount of time has elapsed since the query was first attempted. This
1547
+ value defaults to nil, meaning that all retryable queries are retried regardless of time elapsed,
1548
+ but this can be changed via the `retry_deadline` option in the database config.
1083
1549
 
1084
- # unscope both hidden columns
1085
- posts.unscope(where: :hidden).count
1086
- # => { false => 11, true => 1 }
1550
+ *Adrianna Chang*
1087
1551
 
1088
- # unscope only comments.hidden column
1089
- posts.unscope(where: :"comments.hidden").count
1090
- # => { false => 11 }
1091
- ```
1552
+ * Fix a case where the query cache can return wrong values. See #46044
1553
+
1554
+ *Aaron Patterson*
1092
1555
 
1093
- *Ryuta Kamizono*, *Slava Korolev*
1556
+ * Support MySQL's ssl-mode option for MySQLDatabaseTasks.
1094
1557
 
1095
- * Fix `rewhere` to truly overwrite collided where clause by new where clause.
1558
+ Verifying the identity of the database server requires setting the ssl-mode
1559
+ option to VERIFY_CA or VERIFY_IDENTITY. This option was previously ignored
1560
+ for MySQL database tasks like creating a database and dumping the structure.
1096
1561
 
1097
- ```ruby
1098
- steve = Person.find_by(name: "Steve")
1099
- david = Author.find_by(name: "David")
1562
+ *Petrik de Heus*
1100
1563
 
1101
- relation = Essay.where(writer: steve)
1564
+ * Move `ActiveRecord::InternalMetadata` to an independent object.
1102
1565
 
1103
- # Before
1104
- relation.rewhere(writer: david).to_a # => []
1566
+ `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`.
1105
1567
 
1106
- # After
1107
- relation.rewhere(writer: david).to_a # => [david]
1568
+ *Eileen M. Uchitelle*
1569
+
1570
+ * Deprecate quoting `ActiveSupport::Duration` as an integer
1571
+
1572
+ Using ActiveSupport::Duration as an interpolated bind parameter in a SQL
1573
+ string template is deprecated. To avoid this warning, you should explicitly
1574
+ convert the duration to a more specific database type. For example, if you
1575
+ want to use a duration as an integer number of seconds:
1576
+ ```
1577
+ Record.where("duration = ?", 1.hour.to_i)
1578
+ ```
1579
+ If you want to use a duration as an ISO 8601 string:
1580
+ ```
1581
+ Record.where("duration = ?", 1.hour.iso8601)
1108
1582
  ```
1109
1583
 
1110
- *Ryuta Kamizono*
1584
+ *Aram Greenman*
1111
1585
 
1112
- * Inspect time attributes with subsec and time zone offset.
1586
+ * Allow `QueryMethods#in_order_of` to order by a string column name.
1113
1587
 
1114
1588
  ```ruby
1115
- p Knot.create
1116
- => #<Knot id: 1, created_at: "2016-05-05 01:29:47.116928000 +0000">
1589
+ Post.in_order_of("id", [4,2,3,1]).to_a
1590
+ Post.joins(:author).in_order_of("authors.name", ["Bob", "Anna", "John"]).to_a
1117
1591
  ```
1118
1592
 
1119
- *akinomaeni*, *Jonathan Hefner*
1120
-
1121
- * Deprecate passing a column to `type_cast`.
1593
+ *Igor Kasyanchuk*
1122
1594
 
1123
- *Ryuta Kamizono*
1124
-
1125
- * Deprecate `in_clause_length` and `allowed_index_name_length` in `DatabaseLimits`.
1595
+ * Move `ActiveRecord::SchemaMigration` to an independent object.
1126
1596
 
1127
- *Ryuta Kamizono*
1597
+ `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`.
1128
1598
 
1129
- * Support bulk insert/upsert on relation to preserve scope values.
1599
+ *Eileen M. Uchitelle*
1130
1600
 
1131
- *Josef Šimánek*, *Ryuta Kamizono*
1601
+ * Deprecate `all_connection_pools` and make `connection_pool_list` more explicit.
1132
1602
 
1133
- * Preserve column comment value on changing column name on MySQL.
1603
+ 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`.
1134
1604
 
1135
- *Islam Taha*
1605
+ *Eileen M. Uchitelle*
1136
1606
 
1137
- * Add support for `if_exists` option for removing an index.
1607
+ * Fix connection handler methods to operate on all pools.
1138
1608
 
1139
- The `remove_index` method can take an `if_exists` option. If this is set to true an error won't be raised if the index doesn't exist.
1609
+ `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.
1140
1610
 
1141
1611
  *Eileen M. Uchitelle*
1142
1612
 
1143
- * Remove ibm_db, informix, mssql, oracle, and oracle12 Arel visitors which are not used in the code base.
1144
1613
 
1145
- *Ryuta Kamizono*
1614
+ * Allow ActiveRecord::QueryMethods#select to receive hash values.
1146
1615
 
1147
- * Prevent `build_association` from `touching` a parent record if the record isn't persisted for `has_one` associations.
1616
+ Currently, `select` might receive only raw sql and symbols to define columns and aliases to select.
1148
1617
 
1149
- Fixes #38219.
1618
+ With this change we can provide `hash` as argument, for example:
1150
1619
 
1151
- *Josh Brody*
1620
+ ```ruby
1621
+ Post.joins(:comments).select(posts: [:id, :title, :created_at], comments: [:id, :body, :author_id])
1622
+ #=> "SELECT \"posts\".\"id\", \"posts\".\"title\", \"posts\".\"created_at\", \"comments\".\"id\", \"comments\".\"body\", \"comments\".\"author_id\"
1623
+ # FROM \"posts\" INNER JOIN \"comments\" ON \"comments\".\"post_id\" = \"posts\".\"id\""
1152
1624
 
1153
- * Add support for `if_not_exists` option for adding index.
1625
+ Post.joins(:comments).select(posts: { id: :post_id, title: :post_title }, comments: { id: :comment_id, body: :comment_body })
1626
+ #=> "SELECT posts.id as post_id, posts.title as post_title, comments.id as comment_id, comments.body as comment_body
1627
+ # FROM \"posts\" INNER JOIN \"comments\" ON \"comments\".\"post_id\" = \"posts\".\"id\""
1628
+ ```
1629
+ *Oleksandr Holubenko*, *Josef Šimánek*, *Jean Boussier*
1154
1630
 
1155
- The `add_index` method respects `if_not_exists` option. If it is set to true
1156
- index won't be added.
1631
+ * Adapts virtual attributes on `ActiveRecord::Persistence#becomes`.
1157
1632
 
1158
- Usage:
1633
+ When source and target classes have a different set of attributes adapts
1634
+ attributes such that the extra attributes from target are added.
1159
1635
 
1160
1636
  ```ruby
1161
- add_index :users, :account_id, if_not_exists: true
1162
- ```
1637
+ class Person < ApplicationRecord
1638
+ end
1163
1639
 
1164
- The `if_not_exists` option passed to `create_table` also gets propagated to indexes
1165
- created within that migration so that if table and its indexes exist then there is no
1166
- attempt to create them again.
1640
+ class WebUser < Person
1641
+ attribute :is_admin, :boolean
1642
+ after_initialize :set_admin
1167
1643
 
1168
- *Prathamesh Sonpatki*
1644
+ def set_admin
1645
+ write_attribute(:is_admin, email =~ /@ourcompany\.com$/)
1646
+ end
1647
+ end
1169
1648
 
1170
- * Add `ActiveRecord::Base#previously_new_record?` to show if a record was new before the last save.
1649
+ person = Person.find_by(email: "email@ourcompany.com")
1650
+ person.respond_to? :is_admin
1651
+ # => false
1652
+ person.becomes(WebUser).is_admin?
1653
+ # => true
1654
+ ```
1171
1655
 
1172
- *Tom Ward*
1656
+ *Jacopo Beschi*, *Sampson Crowley*
1173
1657
 
1174
- * Support descending order for `find_each`, `find_in_batches`, and `in_batches`.
1658
+ * Fix `ActiveRecord::QueryMethods#in_order_of` to include `nil`s, to match the
1659
+ behavior of `Enumerable#in_order_of`.
1175
1660
 
1176
- Batch processing methods allow you to work with the records in batches, greatly reducing memory consumption, but records are always batched from oldest id to newest.
1661
+ For example, `Post.in_order_of(:title, [nil, "foo"])` will now include posts
1662
+ with `nil` titles, the same as `Post.all.to_a.in_order_of(:title, [nil, "foo"])`.
1177
1663
 
1178
- This change allows reversing the order, batching from newest to oldest. This is useful when you need to process newer batches of records first.
1664
+ *fatkodima*
1179
1665
 
1180
- Pass `order: :desc` to yield batches in descending order. The default remains `order: :asc`.
1666
+ * Optimize `add_timestamps` to use a single SQL statement.
1181
1667
 
1182
1668
  ```ruby
1183
- Person.find_each(order: :desc) do |person|
1184
- person.party_all_night!
1185
- end
1669
+ add_timestamps :my_table
1186
1670
  ```
1187
1671
 
1188
- *Alexey Vasiliev*
1189
-
1190
- * Fix `insert_all` with enum values.
1672
+ Now results in the following SQL:
1191
1673
 
1192
- Fixes #38716.
1193
-
1194
- *Joel Blum*
1674
+ ```sql
1675
+ ALTER TABLE "my_table" ADD COLUMN "created_at" datetime(6) NOT NULL, ADD COLUMN "updated_at" datetime(6) NOT NULL
1676
+ ```
1195
1677
 
1196
- * Add support for `db:rollback:name` for multiple database applications.
1678
+ *Iliana Hadzhiatanasova*
1197
1679
 
1198
- Multiple database applications will now raise if `db:rollback` is call and recommend using the `db:rollback:[NAME]` to rollback migrations.
1680
+ * Add `drop_enum` migration command for PostgreSQL
1199
1681
 
1200
- *Eileen M. Uchitelle*
1682
+ This does the inverse of `create_enum`. Before dropping an enum, ensure you have
1683
+ dropped columns that depend on it.
1201
1684
 
1202
- * `Relation#pick` now uses already loaded results instead of making another query.
1685
+ *Alex Ghiculescu*
1203
1686
 
1204
- *Eugene Kenny*
1687
+ * Adds support for `if_exists` option when removing a check constraint.
1205
1688
 
1206
- * Deprecate using `return`, `break` or `throw` to exit a transaction block after writes.
1689
+ The `remove_check_constraint` method now accepts an `if_exists` option. If set
1690
+ to true an error won't be raised if the check constraint doesn't exist.
1207
1691
 
1208
- *Dylan Thacker-Smith*
1692
+ *Margaret Parsa* and *Aditya Bhutani*
1209
1693
 
1210
- * Dump the schema or structure of a database when calling `db:migrate:name`.
1694
+ * `find_or_create_by` now try to find a second time if it hits a unicity constraint.
1211
1695
 
1212
- In previous versions of Rails, `rails db:migrate` would dump the schema of the database. In Rails 6, that holds true (`rails db:migrate` dumps all databases' schemas), but `rails db:migrate:name` does not share that behavior.
1696
+ `find_or_create_by` always has been inherently racy, either creating multiple
1697
+ duplicate records or failing with `ActiveRecord::RecordNotUnique` depending on
1698
+ whether a proper unicity constraint was set.
1213
1699
 
1214
- Going forward, calls to `rails db:migrate:name` will dump the schema (or structure) of the database being migrated.
1700
+ `create_or_find_by` was introduced for this use case, however it's quite wasteful
1701
+ when the record is expected to exist most of the time, as INSERT require to send
1702
+ more data than SELECT and require more work from the database. Also on some
1703
+ databases it can actually consume a primary key increment which is undesirable.
1215
1704
 
1216
- *Kyle Thompson*
1705
+ So for case where most of the time the record is expected to exist, `find_or_create_by`
1706
+ can be made race-condition free by re-trying the `find` if the `create` failed
1707
+ with `ActiveRecord::RecordNotUnique`. This assumes that the table has the proper
1708
+ unicity constraints, if not, `find_or_create_by` will still lead to duplicated records.
1217
1709
 
1218
- * Reset the `ActiveRecord::Base` connection after `rails db:migrate:name`.
1710
+ *Jean Boussier*, *Alex Kitchens*
1219
1711
 
1220
- When `rails db:migrate` has finished, it ensures the `ActiveRecord::Base` connection is reset to its original configuration. Going forward, `rails db:migrate:name` will have the same behavior.
1712
+ * Introduce a simpler constructor API for ActiveRecord database adapters.
1221
1713
 
1222
- *Kyle Thompson*
1714
+ Previously the adapter had to know how to build a new raw connection to
1715
+ support reconnect, but also expected to be passed an initial already-
1716
+ established connection.
1223
1717
 
1224
- * Disallow calling `connected_to` on subclasses of `ActiveRecord::Base`.
1718
+ When manually creating an adapter instance, it will now accept a single
1719
+ config hash, and only establish the real connection on demand.
1225
1720
 
1226
- Behavior has not changed here but the previous API could be misleading to people who thought it would switch connections for only that class. `connected_to` switches the context from which we are getting connections, not the connections themselves.
1721
+ *Matthew Draper*
1227
1722
 
1228
- *Eileen M. Uchitelle*, *John Crepezzi*
1723
+ * Avoid redundant `SELECT 1` connection-validation query during DB pool
1724
+ checkout when possible.
1229
1725
 
1230
- * Add support for horizontal sharding to `connects_to` and `connected_to`.
1726
+ If the first query run during a request is known to be idempotent, it can be
1727
+ used directly to validate the connection, saving a network round-trip.
1231
1728
 
1232
- Applications can now connect to multiple shards and switch between their shards in an application. Note that the shard swapping is still a manual process as this change does not include an API for automatic shard swapping.
1729
+ *Matthew Draper*
1233
1730
 
1234
- Usage:
1731
+ * Automatically reconnect broken database connections when safe, even
1732
+ mid-request.
1235
1733
 
1236
- Given the following configuration:
1734
+ When an error occurs while attempting to run a known-idempotent query, and
1735
+ not inside a transaction, it is safe to immediately reconnect to the
1736
+ database server and try again, so this is now the default behavior.
1237
1737
 
1238
- ```yaml
1239
- # config/database.yml
1240
- production:
1241
- primary:
1242
- database: my_database
1243
- primary_shard_one:
1244
- database: my_database_shard_one
1245
- ```
1738
+ This new default should always be safe -- to support that, it's consciously
1739
+ conservative about which queries are considered idempotent -- but if
1740
+ necessary it can be disabled by setting the `connection_retries` connection
1741
+ option to `0`.
1246
1742
 
1247
- Connect to multiple shards:
1743
+ *Matthew Draper*
1248
1744
 
1249
- ```ruby
1250
- class ApplicationRecord < ActiveRecord::Base
1251
- self.abstract_class = true
1745
+ * Avoid removing a PostgreSQL extension when there are dependent objects.
1252
1746
 
1253
- connects_to shards: {
1254
- default: { writing: :primary },
1255
- shard_one: { writing: :primary_shard_one }
1256
- }
1257
- ```
1747
+ Previously, removing an extension also implicitly removed dependent objects. Now, this will raise an error.
1258
1748
 
1259
- Swap between shards in your controller / model code:
1749
+ You can force removing the extension:
1260
1750
 
1261
1751
  ```ruby
1262
- ActiveRecord::Base.connected_to(shard: :shard_one) do
1263
- # Read from shard one
1264
- end
1752
+ disable_extension :citext, force: :cascade
1265
1753
  ```
1266
1754
 
1267
- The horizontal sharding API also supports read replicas. See guides for more details.
1755
+ Fixes #29091.
1268
1756
 
1269
- *Eileen M. Uchitelle*, *John Crepezzi*
1757
+ *fatkodima*
1270
1758
 
1271
- * Deprecate `spec_name` in favor of `name` on database configurations.
1759
+ * Allow nested functions as safe SQL string
1272
1760
 
1273
- The accessors for `spec_name` on `configs_for` and `DatabaseConfig` are deprecated. Please use `name` instead.
1761
+ *Michael Siegfried*
1274
1762
 
1275
- Deprecated behavior:
1763
+ * Allow `destroy_association_async_job=` to be configured with a class string instead of a constant.
1276
1764
 
1277
- ```ruby
1278
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: "development", spec_name: "primary")
1279
- db_config.spec_name
1280
- ```
1765
+ Defers an autoloading dependency between `ActiveRecord::Base` and `ActiveJob::Base`
1766
+ and moves the configuration of `ActiveRecord::DestroyAssociationAsyncJob`
1767
+ from ActiveJob to ActiveRecord.
1281
1768
 
1282
- New behavior:
1769
+ Deprecates `ActiveRecord::ActiveJobRequiredError` and now raises a `NameError`
1770
+ if the job class is unloadable or an `ActiveRecord::ConfigurationError` if
1771
+ `dependent: :destroy_async` is declared on an association but there is no job
1772
+ class configured.
1283
1773
 
1284
- ```ruby
1285
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: "development", name: "primary")
1286
- db_config.name
1287
- ```
1774
+ *Ben Sheldon*
1288
1775
 
1289
- *Eileen M. Uchitelle*
1776
+ * Fix `ActiveRecord::Store` to serialize as a regular Hash
1290
1777
 
1291
- * Add additional database-specific rake tasks for multi-database users.
1778
+ Previously it would serialize as an `ActiveSupport::HashWithIndifferentAccess`
1779
+ which is wasteful and cause problem with YAML safe_load.
1292
1780
 
1293
- Previously, `rails db:create`, `rails db:drop`, and `rails db:migrate` were the only rails tasks that could operate on a single
1294
- database. For example:
1781
+ *Jean Boussier*
1295
1782
 
1296
- ```
1297
- rails db:create
1298
- rails db:create:primary
1299
- rails db:create:animals
1300
- rails db:drop
1301
- rails db:drop:primary
1302
- rails db:drop:animals
1303
- rails db:migrate
1304
- rails db:migrate:primary
1305
- rails db:migrate:animals
1306
- ```
1783
+ * Add `timestamptz` as a time zone aware type for PostgreSQL
1307
1784
 
1308
- With these changes, `rails db:schema:dump`, `rails db:schema:load`, `rails db:structure:dump`, `rails db:structure:load` and
1309
- `rails db:test:prepare` can additionally operate on a single database. For example:
1785
+ This is required for correctly parsing `timestamp with time zone` values in your database.
1310
1786
 
1311
- ```
1312
- rails db:schema:dump
1313
- rails db:schema:dump:primary
1314
- rails db:schema:dump:animals
1315
- rails db:schema:load
1316
- rails db:schema:load:primary
1317
- rails db:schema:load:animals
1318
- rails db:structure:dump
1319
- rails db:structure:dump:primary
1320
- rails db:structure:dump:animals
1321
- rails db:structure:load
1322
- rails db:structure:load:primary
1323
- rails db:structure:load:animals
1324
- rails db:test:prepare
1325
- rails db:test:prepare:primary
1326
- rails db:test:prepare:animals
1787
+ If you don't want this, you can opt out by adding this initializer:
1788
+
1789
+ ```ruby
1790
+ ActiveRecord::Base.time_zone_aware_types -= [:timestamptz]
1327
1791
  ```
1328
1792
 
1329
- *Kyle Thompson*
1793
+ *Alex Ghiculescu*
1330
1794
 
1331
- * Add support for `strict_loading` mode on association declarations.
1795
+ * Add new `ActiveRecord::Base.generates_token_for` API.
1332
1796
 
1333
- Raise an error if attempting to load a record from an association that has been marked as `strict_loading` unless it was explicitly eager loaded.
1797
+ Currently, `signed_id` fulfills the role of generating tokens for e.g.
1798
+ resetting a password. However, signed IDs cannot reflect record state, so
1799
+ if a token is intended to be single-use, it must be tracked in a database at
1800
+ least until it expires.
1334
1801
 
1335
- Usage:
1802
+ With `generates_token_for`, a token can embed data from a record. When
1803
+ using the token to fetch the record, the data from the token and the current
1804
+ data from the record will be compared. If the two do not match, the token
1805
+ will be treated as invalid, the same as if it had expired. For example:
1336
1806
 
1337
1807
  ```ruby
1338
- class Developer < ApplicationRecord
1339
- has_many :projects, strict_loading: true
1808
+ class User < ActiveRecord::Base
1809
+ has_secure_password
1810
+
1811
+ generates_token_for :password_reset, expires_in: 15.minutes do
1812
+ # A password's BCrypt salt changes when the password is updated.
1813
+ # By embedding (part of) the salt in a token, the token will
1814
+ # expire when the password is updated.
1815
+ BCrypt::Password.new(password_digest).salt[-10..]
1816
+ end
1340
1817
  end
1341
1818
 
1342
- dev = Developer.first
1343
- dev.projects.first
1344
- # => ActiveRecord::StrictLoadingViolationError: The projects association is marked as strict_loading and cannot be lazily loaded.
1819
+ user = User.first
1820
+ token = user.generate_token_for(:password_reset)
1821
+
1822
+ User.find_by_token_for(:password_reset, token) # => user
1823
+
1824
+ user.update!(password: "new password")
1825
+ User.find_by_token_for(:password_reset, token) # => nil
1345
1826
  ```
1346
1827
 
1347
- *Kevin Deisz*
1828
+ *Jonathan Hefner*
1348
1829
 
1349
- * Add support for `strict_loading` mode to prevent lazy loading of records.
1830
+ * Optimize Active Record batching for whole table iterations.
1350
1831
 
1351
- Raise an error if a parent record is marked as `strict_loading` and attempts to lazily load its associations. This is useful for finding places you may want to preload an association and avoid additional queries.
1832
+ Previously, `in_batches` got all the ids and constructed an `IN`-based query for each batch.
1833
+ When iterating over the whole tables, this approach is not optimal as it loads unneeded ids and
1834
+ `IN` queries with lots of items are slow.
1352
1835
 
1353
- Usage:
1836
+ Now, whole table iterations use range iteration (`id >= x AND id <= y`) by default which can make iteration
1837
+ several times faster. E.g., tested on a PostgreSQL table with 10 million records: querying (`253s` vs `30s`),
1838
+ updating (`288s` vs `124s`), deleting (`268s` vs `83s`).
1839
+
1840
+ Only whole table iterations use this style of iteration by default. You can disable this behavior by passing `use_ranges: false`.
1841
+ If you iterate over the table and the only condition is, e.g., `archived_at: nil` (and only a tiny fraction
1842
+ of the records are archived), it makes sense to opt in to this approach:
1354
1843
 
1355
1844
  ```ruby
1356
- dev = Developer.strict_loading.first
1357
- dev.audit_logs.to_a
1358
- # => ActiveRecord::StrictLoadingViolationError: Developer is marked as strict_loading and AuditLog cannot be lazily loaded.
1845
+ Project.where(archived_at: nil).in_batches(use_ranges: true) do |relation|
1846
+ # do something
1847
+ end
1359
1848
  ```
1360
1849
 
1361
- *Eileen M. Uchitelle*, *Aaron Patterson*
1850
+ See #45414 for more details.
1362
1851
 
1363
- * Add support for PostgreSQL 11+ partitioned indexes when using `upsert_all`.
1852
+ *fatkodima*
1364
1853
 
1365
- *Sebastián Palma*
1854
+ * `.with` query method added. Construct common table expressions with ease and get `ActiveRecord::Relation` back.
1366
1855
 
1367
- * Adds support for `if_not_exists` to `add_column` and `if_exists` to `remove_column`.
1856
+ ```ruby
1857
+ Post.with(posts_with_comments: Post.where("comments_count > ?", 0))
1858
+ # => ActiveRecord::Relation
1859
+ # WITH posts_with_comments AS (SELECT * FROM posts WHERE (comments_count > 0)) SELECT * FROM posts
1860
+ ```
1368
1861
 
1369
- Applications can set their migrations to ignore exceptions raised when adding a column that already exists or when removing a column that does not exist.
1862
+ *Vlado Cingel*
1370
1863
 
1371
- Example Usage:
1864
+ * Don't establish a new connection if an identical pool exists already.
1372
1865
 
1373
- ```ruby
1374
- class AddColumnTitle < ActiveRecord::Migration[6.1]
1375
- def change
1376
- add_column :posts, :title, :string, if_not_exists: true
1377
- end
1378
- end
1379
- ```
1866
+ 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.
1380
1867
 
1381
- ```ruby
1382
- class RemoveColumnTitle < ActiveRecord::Migration[6.1]
1383
- def change
1384
- remove_column :posts, :title, if_exists: true
1385
- end
1386
- end
1387
- ```
1868
+ 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.
1388
1869
 
1389
1870
  *Eileen M. Uchitelle*
1390
1871
 
1391
- * Regexp-escape table name for MS SQL Server.
1872
+ * Update `db:prepare` task to load schema when an uninitialized database exists, and dump schema after migrations.
1873
+
1874
+ *Ben Sheldon*
1392
1875
 
1393
- Add `Regexp.escape` to one method in ActiveRecord, so that table names with regular expression characters in them work as expected. Since MS SQL Server uses "[" and "]" to quote table and column names, and those characters are regular expression characters, methods like `pluck` and `select` fail in certain cases when used with the MS SQL Server adapter.
1876
+ * Fix supporting timezone awareness for `tsrange` and `tstzrange` array columns.
1394
1877
 
1395
- *Larry Reid*
1878
+ ```ruby
1879
+ # In database migrations
1880
+ add_column :shops, :open_hours, :tsrange, array: true
1881
+ # In app config
1882
+ ActiveRecord::Base.time_zone_aware_types += [:tsrange]
1883
+ # In the code times are properly converted to app time zone
1884
+ Shop.create!(open_hours: [Time.current..8.hour.from_now])
1885
+ ```
1396
1886
 
1397
- * Store advisory locks on their own named connection.
1887
+ *Wojciech Wnętrzak*
1398
1888
 
1399
- Previously advisory locks were taken out against a connection when a migration started. This works fine in single database applications but doesn't work well when migrations need to open new connections which results in the lock getting dropped.
1889
+ * Introduce strategy pattern for executing migrations.
1400
1890
 
1401
- In order to fix this we are storing the advisory lock on a new connection with the connection specification name `AdvisoryLockBase`. The caveat is that we need to maintain at least 2 connections to a database while migrations are running in order to do this.
1891
+ By default, migrations will use a strategy object that delegates the method
1892
+ to the connection adapter. Consumers can implement custom strategy objects
1893
+ to change how their migrations run.
1402
1894
 
1403
- *Eileen M. Uchitelle*, *John Crepezzi*
1895
+ *Adrianna Chang*
1404
1896
 
1405
- * Allow schema cache path to be defined in the database configuration file.
1897
+ * Add adapter option disallowing foreign keys
1406
1898
 
1407
- For example:
1899
+ This adds a new option to be added to `database.yml` which enables skipping
1900
+ foreign key constraints usage even if the underlying database supports them.
1408
1901
 
1902
+ Usage:
1409
1903
  ```yaml
1410
1904
  development:
1411
- adapter: postgresql
1412
- database: blog_development
1413
- pool: 5
1414
- schema_cache_path: tmp/schema/main.yml
1905
+ <<: *default
1906
+ database: storage/development.sqlite3
1907
+ foreign_keys: false
1415
1908
  ```
1416
1909
 
1417
- *Katrina Owen*
1910
+ *Paulo Barros*
1418
1911
 
1419
- * Deprecate `#remove_connection` in favor of `#remove_connection_pool` when called on the handler.
1912
+ * Add configurable deprecation warning for singular associations
1420
1913
 
1421
- `#remove_connection` is deprecated in order to support returning a `DatabaseConfig` object instead of a `Hash`. Use `#remove_connection_pool`, `#remove_connection` will be removed in Rails 7.0.
1914
+ This adds a deprecation warning when using the plural name of a singular associations in `where`.
1915
+ It is possible to opt into the new more performant behavior with `config.active_record.allow_deprecated_singular_associations_name = false`
1422
1916
 
1423
- *Eileen M. Uchitelle*, *John Crepezzi*
1917
+ *Adam Hess*
1424
1918
 
1425
- * Deprecate `#default_hash` and it's alias `#[]` on database configurations.
1919
+ * Run transactional callbacks on the freshest instance to save a given
1920
+ record within a transaction.
1426
1921
 
1427
- Applications should use `configs_for`. `#default_hash` and `#[]` will be removed in Rails 7.0.
1922
+ When multiple Active Record instances change the same record within a
1923
+ transaction, Rails runs `after_commit` or `after_rollback` callbacks for
1924
+ only one of them. `config.active_record.run_commit_callbacks_on_first_saved_instances_in_transaction`
1925
+ was added to specify how Rails chooses which instance receives the
1926
+ callbacks. The framework defaults were changed to use the new logic.
1428
1927
 
1429
- *Eileen M. Uchitelle*, *John Crepezzi*
1928
+ When `config.active_record.run_commit_callbacks_on_first_saved_instances_in_transaction`
1929
+ is `true`, transactional callbacks are run on the first instance to save,
1930
+ even though its instance state may be stale.
1430
1931
 
1431
- * Add scale support to `ActiveRecord::Validations::NumericalityValidator`.
1932
+ When it is `false`, which is the new framework default starting with version
1933
+ 7.1, transactional callbacks are run on the instances with the freshest
1934
+ instance state. Those instances are chosen as follows:
1432
1935
 
1433
- *Gannon McGibbon*
1936
+ - In general, run transactional callbacks on the last instance to save a
1937
+ given record within the transaction.
1938
+ - There are two exceptions:
1939
+ - If the record is created within the transaction, then updated by
1940
+ another instance, `after_create_commit` callbacks will be run on the
1941
+ second instance. This is instead of the `after_update_commit`
1942
+ callbacks that would naively be run based on that instance’s state.
1943
+ - If the record is destroyed within the transaction, then
1944
+ `after_destroy_commit` callbacks will be fired on the last destroyed
1945
+ instance, even if a stale instance subsequently performed an update
1946
+ (which will have affected 0 rows).
1434
1947
 
1435
- * Find orphans by looking for missing relations through chaining `where.missing`:
1948
+ *Cameron Bothner and Mitch Vollebregt*
1436
1949
 
1437
- Before:
1950
+ * Enable strict strings mode for `SQLite3Adapter`.
1951
+
1952
+ Configures SQLite with a strict strings mode, which disables double-quoted string literals.
1953
+
1954
+ SQLite has some quirks around double-quoted string literals.
1955
+ It first tries to consider double-quoted strings as identifier names, but if they don't exist
1956
+ it then considers them as string literals. Because of this, typos can silently go unnoticed.
1957
+ For example, it is possible to create an index for a non existing column.
1958
+ See [SQLite documentation](https://www.sqlite.org/quirks.html#double_quoted_string_literals_are_accepted) for more details.
1959
+
1960
+ If you don't want this behavior, you can disable it via:
1438
1961
 
1439
1962
  ```ruby
1440
- Post.left_joins(:author).where(authors: { id: nil })
1963
+ # config/application.rb
1964
+ config.active_record.sqlite3_adapter_strict_strings_by_default = false
1441
1965
  ```
1442
1966
 
1443
- After:
1967
+ Fixes #27782.
1968
+
1969
+ *fatkodima*, *Jean Boussier*
1970
+
1971
+ * Resolve issue where a relation cache_version could be left stale.
1972
+
1973
+ Previously, when `reset` was called on a relation object it did not reset the cache_versions
1974
+ ivar. This led to a confusing situation where despite having the correct data the relation
1975
+ still reported a stale cache_version.
1976
+
1977
+ Usage:
1444
1978
 
1445
1979
  ```ruby
1446
- Post.where.missing(:author)
1980
+ developers = Developer.all
1981
+ developers.cache_version
1982
+
1983
+ Developer.update_all(updated_at: Time.now.utc + 1.second)
1984
+
1985
+ developers.cache_version # Stale cache_version
1986
+ developers.reset
1987
+ developers.cache_version # Returns the current correct cache_version
1447
1988
  ```
1448
1989
 
1449
- *Tom Rossi*
1990
+ Fixes #45341.
1450
1991
 
1451
- * Ensure `:reading` connections always raise if a write is attempted.
1992
+ *Austen Madden*
1452
1993
 
1453
- Now Rails will raise an `ActiveRecord::ReadOnlyError` if any connection on the reading handler attempts to make a write. If your reading role needs to write you should name the role something other than `:reading`.
1994
+ * Add support for exclusion constraints (PostgreSQL-only).
1454
1995
 
1455
- *Eileen M. Uchitelle*
1996
+ ```ruby
1997
+ add_exclusion_constraint :invoices, "daterange(start_date, end_date) WITH &&", using: :gist, name: "invoices_date_overlap"
1998
+ remove_exclusion_constraint :invoices, name: "invoices_date_overlap"
1999
+ ```
1456
2000
 
1457
- * Deprecate `"primary"` as the `connection_specification_name` for `ActiveRecord::Base`.
2001
+ See PostgreSQL's [`CREATE TABLE ... EXCLUDE ...`](https://www.postgresql.org/docs/12/sql-createtable.html#SQL-CREATETABLE-EXCLUDE) documentation for more on exclusion constraints.
1458
2002
 
1459
- `"primary"` has been deprecated as the `connection_specification_name` for `ActiveRecord::Base` in favor of using `"ActiveRecord::Base"`. This change affects calls to `ActiveRecord::Base.connection_handler.retrieve_connection` and `ActiveRecord::Base.connection_handler.remove_connection`. If you're calling these methods with `"primary"`, please switch to `"ActiveRecord::Base"`.
2003
+ *Alex Robbin*
1460
2004
 
1461
- *Eileen M. Uchitelle*, *John Crepezzi*
2005
+ * `change_column_null` raises if a non-boolean argument is provided
1462
2006
 
1463
- * Add `ActiveRecord::Validations::NumericalityValidator` with
1464
- support for casting floats using a database columns' precision value.
2007
+ Previously if you provided a non-boolean argument, `change_column_null` would
2008
+ treat it as truthy and make your column nullable. This could be surprising, so now
2009
+ the input must be either `true` or `false`.
1465
2010
 
1466
- *Gannon McGibbon*
2011
+ ```ruby
2012
+ change_column_null :table, :column, true # good
2013
+ change_column_null :table, :column, false # good
2014
+ change_column_null :table, :column, from: true, to: false # raises (previously this made the column nullable)
2015
+ ```
1467
2016
 
1468
- * Enforce fresh ETag header after a collection's contents change by adding
1469
- ActiveRecord::Relation#cache_key_with_version. This method will be used by
1470
- ActionController::ConditionalGet to ensure that when collection cache versioning
1471
- is enabled, requests using ConditionalGet don't return the same ETag header
1472
- after a collection is modified.
2017
+ *Alex Ghiculescu*
1473
2018
 
1474
- Fixes #38078.
2019
+ * Enforce limit on table names length.
1475
2020
 
1476
- *Aaron Lipman*
2021
+ Fixes #45130.
1477
2022
 
1478
- * Skip test database when running `db:create` or `db:drop` in development
1479
- with `DATABASE_URL` set.
2023
+ *fatkodima*
1480
2024
 
1481
- *Brian Buchalter*
2025
+ * Adjust the minimum MariaDB version for check constraints support.
1482
2026
 
1483
- * Don't allow mutations on the database configurations hash.
2027
+ *Eddie Lebow*
1484
2028
 
1485
- Freeze the configurations hash to disallow directly changing it. If applications need to change the hash, for example to create databases for parallelization, they should use the `DatabaseConfig` object directly.
2029
+ * Fix Hstore deserialize regression.
1486
2030
 
1487
- Before:
2031
+ *edsharp*
2032
+
2033
+ * Add validity for PostgreSQL indexes.
1488
2034
 
1489
2035
  ```ruby
1490
- @db_config = ActiveRecord::Base.configurations.configs_for(env_name: "test", spec_name: "primary")
1491
- @db_config.configuration_hash.merge!(idle_timeout: "0.02")
2036
+ connection.index_exists?(:users, :email, valid: true)
2037
+ connection.indexes(:users).select(&:valid?)
1492
2038
  ```
1493
2039
 
1494
- After:
2040
+ *fatkodima*
2041
+
2042
+ * Fix eager loading for models without primary keys.
2043
+
2044
+ *Anmol Chopra*, *Matt Lawrence*, and *Jonathan Hefner*
2045
+
2046
+ * Avoid validating a unique field if it has not changed and is backed by a unique index.
2047
+
2048
+ Previously, when saving a record, Active Record will perform an extra query to check for the
2049
+ uniqueness of each attribute having a `uniqueness` validation, even if that attribute hasn't changed.
2050
+ If the database has the corresponding unique index, then this validation can never fail for persisted
2051
+ records, and we could safely skip it.
2052
+
2053
+ *fatkodima*
2054
+
2055
+ * Stop setting `sql_auto_is_null`
2056
+
2057
+ Since version 5.5 the default has been off, we no longer have to manually turn it off.
2058
+
2059
+ *Adam Hess*
2060
+
2061
+ * Fix `touch` to raise an error for readonly columns.
2062
+
2063
+ *fatkodima*
2064
+
2065
+ * Add ability to ignore tables by regexp for SQL schema dumps.
1495
2066
 
1496
2067
  ```ruby
1497
- @db_config = ActiveRecord::Base.configurations.configs_for(env_name: "test", spec_name: "primary")
1498
- config = @db_config.configuration_hash.merge(idle_timeout: "0.02")
1499
- db_config = ActiveRecord::DatabaseConfigurations::HashConfig.new(@db_config.env_name, @db_config.spec_name, config)
2068
+ ActiveRecord::SchemaDumper.ignore_tables = [/^_/]
1500
2069
  ```
1501
2070
 
1502
- *Eileen M. Uchitelle*, *John Crepezzi*
1503
-
1504
- * Remove `:connection_id` from the `sql.active_record` notification.
2071
+ *fatkodima*
1505
2072
 
1506
- *Aaron Patterson*, *Rafael Mendonça França*
2073
+ * Avoid queries when performing calculations on contradictory relations.
1507
2074
 
1508
- * The `:name` key will no longer be returned as part of `DatabaseConfig#configuration_hash`. Please use `DatabaseConfig#owner_name` instead.
2075
+ Previously calculations would make a query even when passed a
2076
+ contradiction, such as `User.where(id: []).count`. We no longer perform a
2077
+ query in that scenario.
1509
2078
 
1510
- *Eileen M. Uchitelle*, *John Crepezzi*
2079
+ This applies to the following calculations: `count`, `sum`, `average`,
2080
+ `minimum` and `maximum`
1511
2081
 
1512
- * ActiveRecord's `belongs_to_required_by_default` flag can now be set per model.
2082
+ *Luan Vieira, John Hawthorn and Daniel Colson*
1513
2083
 
1514
- You can now opt-out/opt-in specific models from having their associations required
1515
- by default.
2084
+ * Allow using aliased attributes with `insert_all`/`upsert_all`.
1516
2085
 
1517
- This change is meant to ease the process of migrating all your models to have
1518
- their association required.
2086
+ ```ruby
2087
+ class Book < ApplicationRecord
2088
+ alias_attribute :title, :name
2089
+ end
1519
2090
 
1520
- *Edouard Chin*
2091
+ Book.insert_all [{ title: "Remote", author_id: 1 }], returning: :title
2092
+ ```
1521
2093
 
1522
- * The `connection_config` method has been deprecated, please use `connection_db_config` instead which will return a `DatabaseConfigurations::DatabaseConfig` instead of a `Hash`.
2094
+ *fatkodima*
1523
2095
 
1524
- *Eileen M. Uchitelle*, *John Crepezzi*
2096
+ * Support encrypted attributes on columns with default db values.
1525
2097
 
1526
- * Retain explicit selections on the base model after applying `includes` and `joins`.
2098
+ This adds support for encrypted attributes defined on columns with default values.
2099
+ It will encrypt those values at creation time. Before, it would raise an
2100
+ error unless `config.active_record.encryption.support_unencrypted_data` was true.
1527
2101
 
1528
- Resolves #34889.
2102
+ *Jorge Manrubia* and *Dima Fatko*
1529
2103
 
1530
- *Patrick Rebsch*
2104
+ * Allow overriding `reading_request?` in `DatabaseSelector::Resolver`
1531
2105
 
1532
- * The `database` kwarg is deprecated without replacement because it can't be used for sharding and creates an issue if it's used during a request. Applications that need to create new connections should use `connects_to` instead.
2106
+ The default implementation checks if a request is a `get?` or `head?`,
2107
+ but you can now change it to anything you like. If the method returns true,
2108
+ `Resolver#read` gets called meaning the request could be served by the
2109
+ replica database.
1533
2110
 
1534
- *Eileen M. Uchitelle*, *John Crepezzi*
2111
+ *Alex Ghiculescu*
1535
2112
 
1536
- * Allow attributes to be fetched from Arel node groupings.
2113
+ * Remove `ActiveRecord.legacy_connection_handling`.
1537
2114
 
1538
- *Jeff Emminger*, *Gannon McGibbon*
2115
+ *Eileen M. Uchitelle*
1539
2116
 
1540
- * A database URL can now contain a querystring value that contains an equal sign. This is needed to support passing PostgreSQL `options`.
2117
+ * `rails db:schema:{dump,load}` now checks `ENV["SCHEMA_FORMAT"]` before config
1541
2118
 
1542
- *Joshua Flanagan*
2119
+ Since `rails db:structure:{dump,load}` was deprecated there wasn't a simple
2120
+ way to dump a schema to both SQL and Ruby formats. You can now do this with
2121
+ an environment variable. For example:
1543
2122
 
1544
- * Calling methods like `establish_connection` with a `Hash` which is invalid (eg: no `adapter`) will now raise an error the same way as connections defined in `config/database.yml`.
2123
+ ```
2124
+ SCHEMA_FORMAT=sql rake db:schema:dump
2125
+ ```
1545
2126
 
1546
- *John Crepezzi*
2127
+ *Alex Ghiculescu*
1547
2128
 
1548
- * Specifying `implicit_order_column` now subsorts the records by primary key if available to ensure deterministic results.
2129
+ * Fixed MariaDB default function support.
1549
2130
 
1550
- *Paweł Urbanek*
2131
+ Defaults would be written wrong in "db/schema.rb" and not work correctly
2132
+ if using `db:schema:load`. Further more the function name would be
2133
+ added as string content when saving new records.
1551
2134
 
1552
- * `where(attr => [])` now loads an empty result without making a query.
2135
+ *kaspernj*
1553
2136
 
1554
- *John Hawthorn*
2137
+ * Add `active_record.destroy_association_async_batch_size` configuration
1555
2138
 
1556
- * Fixed the performance regression for `primary_keys` introduced MySQL 8.0.
2139
+ This allows applications to specify the maximum number of records that will
2140
+ be destroyed in a single background job by the `dependent: :destroy_async`
2141
+ association option. By default, the current behavior will remain the same:
2142
+ when a parent record is destroyed, all dependent records will be destroyed
2143
+ in a single background job. If the number of dependent records is greater
2144
+ than this configuration, the records will be destroyed in multiple
2145
+ background jobs.
1557
2146
 
1558
- *Hiroyuki Ishii*
2147
+ *Nick Holden*
1559
2148
 
1560
- * Add support for `belongs_to` to `has_many` inversing.
2149
+ * Fix `remove_foreign_key` with `:if_exists` option when foreign key actually exists.
1561
2150
 
1562
- *Gannon McGibbon*
2151
+ *fatkodima*
1563
2152
 
1564
- * Allow length configuration for `has_secure_token` method. The minimum length
1565
- is set at 24 characters.
2153
+ * Remove `--no-comments` flag in structure dumps for PostgreSQL
1566
2154
 
1567
- Before:
2155
+ This broke some apps that used custom schema comments. If you don't want
2156
+ comments in your structure dump, you can use:
1568
2157
 
1569
2158
  ```ruby
1570
- has_secure_token :auth_token
2159
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = ['--no-comments']
1571
2160
  ```
1572
2161
 
1573
- After:
2162
+ *Alex Ghiculescu*
1574
2163
 
1575
- ```ruby
1576
- has_secure_token :default_token # 24 characters
1577
- has_secure_token :auth_token, length: 36 # 36 characters
1578
- has_secure_token :invalid_token, length: 12 # => ActiveRecord::SecureToken::MinimumLengthError
1579
- ```
2164
+ * Reduce the memory footprint of fixtures accessors.
1580
2165
 
1581
- *Bernardo de Araujo*
2166
+ Until now fixtures accessors were eagerly defined using `define_method`.
2167
+ So the memory usage was directly dependent of the number of fixtures and
2168
+ test suites.
1582
2169
 
1583
- * Deprecate `DatabaseConfigurations#to_h`. These connection hashes are still available via `ActiveRecord::Base.configurations.configs_for`.
2170
+ Instead fixtures accessors are now implemented with `method_missing`,
2171
+ so they incur much less memory and CPU overhead.
1584
2172
 
1585
- *Eileen Uchitelle*, *John Crepezzi*
2173
+ *Jean Boussier*
1586
2174
 
1587
- * Add `DatabaseConfig#configuration_hash` to return database configuration hashes with symbol keys, and use all symbol-key configuration hashes internally. Deprecate `DatabaseConfig#config` which returns a String-keyed `Hash` with the same values.
2175
+ * Fix `config.active_record.destroy_association_async_job` configuration
1588
2176
 
1589
- *John Crepezzi*, *Eileen Uchitelle*
2177
+ `config.active_record.destroy_association_async_job` should allow
2178
+ applications to specify the job that will be used to destroy associated
2179
+ records in the background for `has_many` associations with the
2180
+ `dependent: :destroy_async` option. Previously, that was ignored, which
2181
+ meant the default `ActiveRecord::DestroyAssociationAsyncJob` always
2182
+ destroyed records in the background.
1590
2183
 
1591
- * Allow column names to be passed to `remove_index` positionally along with other options.
2184
+ *Nick Holden*
1592
2185
 
1593
- Passing other options can be necessary to make `remove_index` correctly reversible.
2186
+ * Fix `change_column_comment` to preserve column's AUTO_INCREMENT in the MySQL adapter
1594
2187
 
1595
- Before:
2188
+ *fatkodima*
1596
2189
 
1597
- add_index :reports, :report_id # => works
1598
- add_index :reports, :report_id, unique: true # => works
1599
- remove_index :reports, :report_id # => works
1600
- remove_index :reports, :report_id, unique: true # => ArgumentError
2190
+ * Fix quoting of `ActiveSupport::Duration` and `Rational` numbers in the MySQL adapter.
1601
2191
 
1602
- After:
2192
+ *Kevin McPhillips*
1603
2193
 
1604
- remove_index :reports, :report_id, unique: true # => works
2194
+ * Allow column name with COLLATE (e.g., title COLLATE "C") as safe SQL string
1605
2195
 
1606
- *Eugene Kenny*
2196
+ *Shugo Maeda*
1607
2197
 
1608
- * Allow bulk `ALTER` statements to drop and recreate indexes with the same name.
2198
+ * Permit underscores in the VERSION argument to database rake tasks.
1609
2199
 
1610
- *Eugene Kenny*
2200
+ *Eddie Lebow*
1611
2201
 
1612
- * `insert`, `insert_all`, `upsert`, and `upsert_all` now clear the query cache.
2202
+ * Reversed the order of `INSERT` statements in `structure.sql` dumps
1613
2203
 
1614
- *Eugene Kenny*
2204
+ This should decrease the likelihood of merge conflicts. New migrations
2205
+ will now be added at the top of the list.
1615
2206
 
1616
- * Call `while_preventing_writes` directly from `connected_to`.
2207
+ For existing apps, there will be a large diff the next time `structure.sql`
2208
+ is generated.
1617
2209
 
1618
- In some cases application authors want to use the database switching middleware and make explicit calls with `connected_to`. It's possible for an app to turn off writes and not turn them back on by the time we call `connected_to(role: :writing)`.
2210
+ *Alex Ghiculescu*, *Matt Larraz*
1619
2211
 
1620
- This change allows apps to fix this by assuming if a role is writing we want to allow writes, except in the case it's explicitly turned off.
2212
+ * Fix PG.connect keyword arguments deprecation warning on ruby 2.7
1621
2213
 
1622
- *Eileen M. Uchitelle*
2214
+ Fixes #44307.
1623
2215
 
1624
- * Improve detection of ActiveRecord::StatementTimeout with mysql2 adapter in the edge case when the query is terminated during filesort.
2216
+ *Nikita Vasilevsky*
1625
2217
 
1626
- *Kir Shatrov*
2218
+ * Fix dropping DB connections after serialization failures and deadlocks.
1627
2219
 
1628
- * Stop trying to read yaml file fixtures when loading Active Record fixtures.
2220
+ Prior to 6.1.4, serialization failures and deadlocks caused rollbacks to be
2221
+ issued for both real transactions and savepoints. This breaks MySQL which
2222
+ disallows rollbacks of savepoints following a deadlock.
1629
2223
 
1630
- *Gannon McGibbon*
2224
+ 6.1.4 removed these rollbacks, for both transactions and savepoints, causing
2225
+ the DB connection to be left in an unknown state and thus discarded.
1631
2226
 
1632
- * Deprecate `.reorder(nil)` with `.first` / `.first!` taking non-deterministic result.
2227
+ These rollbacks are now restored, except for savepoints on MySQL.
1633
2228
 
1634
- To continue taking non-deterministic result, use `.take` / `.take!` instead.
2229
+ *Thomas Morgan*
1635
2230
 
1636
- *Ryuta Kamizono*
2231
+ * Make `ActiveRecord::ConnectionPool` Fiber-safe
1637
2232
 
1638
- * Preserve user supplied joins order as much as possible.
2233
+ When `ActiveSupport::IsolatedExecutionState.isolation_level` is set to `:fiber`,
2234
+ the connection pool now supports multiple Fibers from the same Thread checking
2235
+ out connections from the pool.
1639
2236
 
1640
- Fixes #36761, #34328, #24281, #12953.
2237
+ *Alex Matchneer*
1641
2238
 
1642
- *Ryuta Kamizono*
2239
+ * Add `update_attribute!` to `ActiveRecord::Persistence`
2240
+
2241
+ Similar to `update_attribute`, but raises `ActiveRecord::RecordNotSaved` when a `before_*` callback throws `:abort`.
1643
2242
 
1644
- * Allow `matches_regex` and `does_not_match_regexp` on the MySQL Arel visitor.
2243
+ ```ruby
2244
+ class Topic < ActiveRecord::Base
2245
+ before_save :check_title
1645
2246
 
1646
- *James Pearson*
2247
+ def check_title
2248
+ throw(:abort) if title == "abort"
2249
+ end
2250
+ end
1647
2251
 
1648
- * Allow specifying fixtures to be ignored by setting `ignore` in YAML file's '_fixture' section.
2252
+ topic = Topic.create(title: "Test Title")
2253
+ # #=> #<Topic title: "Test Title">
2254
+ topic.update_attribute!(:title, "Another Title")
2255
+ # #=> #<Topic title: "Another Title">
2256
+ topic.update_attribute!(:title, "abort")
2257
+ # raises ActiveRecord::RecordNotSaved
2258
+ ```
1649
2259
 
1650
- *Tongfei Gao*
2260
+ *Drew Tempelmeyer*
1651
2261
 
1652
- * Make the DATABASE_URL env variable only affect the primary connection. Add new env variables for multiple databases.
2262
+ * Avoid loading every record in `ActiveRecord::Relation#pretty_print`
1653
2263
 
1654
- *John Crepezzi*, *Eileen Uchitelle*
2264
+ ```ruby
2265
+ # Before
2266
+ pp Foo.all # Loads the whole table.
1655
2267
 
1656
- * Add a warning for enum elements with 'not_' prefix.
2268
+ # After
2269
+ pp Foo.all # Shows 10 items and an ellipsis.
2270
+ ```
1657
2271
 
1658
- class Foo
1659
- enum status: [:sent, :not_sent]
1660
- end
2272
+ *Ulysse Buonomo*
1661
2273
 
1662
- *Edu Depetris*
2274
+ * Change `QueryMethods#in_order_of` to drop records not listed in values.
1663
2275
 
1664
- * Make currency symbols optional for money column type in PostgreSQL.
2276
+ `in_order_of` now filters down to the values provided, to match the behavior of the `Enumerable` version.
1665
2277
 
1666
- *Joel Schneider*
2278
+ *Kevin Newton*
1667
2279
 
1668
- * Add support for beginless ranges, introduced in Ruby 2.7.
2280
+ * Allow named expression indexes to be revertible.
1669
2281
 
1670
- *Josh Goodall*
2282
+ 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.
1671
2283
 
1672
- * Add `database_exists?` method to connection adapters to check if a database exists.
2284
+ ```ruby
2285
+ add_index(:settings, "(data->'property')", using: :gin, name: :index_settings_data_property)
2286
+ ```
1673
2287
 
1674
- *Guilherme Mansur*
2288
+ Fixes #43331.
1675
2289
 
1676
- * Loading the schema for a model that has no `table_name` raises a `TableNotSpecified` error.
2290
+ *Oliver Günther*
1677
2291
 
1678
- *Guilherme Mansur*, *Eugene Kenny*
2292
+ * Fix incorrect argument in PostgreSQL structure dump tasks.
1679
2293
 
1680
- * PostgreSQL: Fix GROUP BY with ORDER BY virtual count attribute.
2294
+ Updating the `--no-comment` argument added in Rails 7 to the correct `--no-comments` argument.
1681
2295
 
1682
- Fixes #36022.
2296
+ *Alex Dent*
1683
2297
 
1684
- *Ryuta Kamizono*
2298
+ * Fix migration compatibility to create SQLite references/belongs_to column as integer when migration version is 6.0.
1685
2299
 
1686
- * Make ActiveRecord `ConnectionPool.connections` method thread-safe.
2300
+ Reference/belongs_to in migrations with version 6.0 were creating columns as
2301
+ bigint instead of integer for the SQLite Adapter.
2302
+
2303
+ *Marcelo Lauxen*
2304
+
2305
+ * Fix `QueryMethods#in_order_of` to handle empty order list.
1687
2306
 
1688
- Fixes #36465.
2307
+ ```ruby
2308
+ Post.in_order_of(:id, []).to_a
2309
+ ```
1689
2310
 
1690
- *Jeff Doering*
2311
+ Also more explicitly set the column as secondary order, so that any other
2312
+ value is still ordered.
2313
+
2314
+ *Jean Boussier*
1691
2315
 
1692
- * Add support for multiple databases to `rails db:abort_if_pending_migrations`.
2316
+ * Fix quoting of column aliases generated by calculation methods.
1693
2317
 
1694
- *Mark Lee*
2318
+ Since the alias is derived from the table name, we can't assume the result
2319
+ is a valid identifier.
1695
2320
 
1696
- * Fix sqlite3 collation parsing when using decimal columns.
2321
+ ```ruby
2322
+ class Test < ActiveRecord::Base
2323
+ self.table_name = '1abc'
2324
+ end
2325
+ Test.group(:id).count
2326
+ # syntax error at or near "1" (ActiveRecord::StatementInvalid)
2327
+ # LINE 1: SELECT COUNT(*) AS count_all, "1abc"."id" AS 1abc_id FROM "1...
2328
+ ```
1697
2329
 
1698
- *Martin R. Schuster*
2330
+ *Jean Boussier*
1699
2331
 
1700
- * Fix invalid schema when primary key column has a comment.
2332
+ * Add `authenticate_by` when using `has_secure_password`.
1701
2333
 
1702
- Fixes #29966.
2334
+ `authenticate_by` is intended to replace code like the following, which
2335
+ returns early when a user with a matching email is not found:
1703
2336
 
1704
- *Guilherme Goettems Schneider*
2337
+ ```ruby
2338
+ User.find_by(email: "...")&.authenticate("...")
2339
+ ```
1705
2340
 
1706
- * Fix table comment also being applied to the primary key column.
2341
+ Such code is vulnerable to timing-based enumeration attacks, wherein an
2342
+ attacker can determine if a user account with a given email exists. After
2343
+ confirming that an account exists, the attacker can try passwords associated
2344
+ with that email address from other leaked databases, in case the user
2345
+ re-used a password across multiple sites (a common practice). Additionally,
2346
+ knowing an account email address allows the attacker to attempt a targeted
2347
+ phishing ("spear phishing") attack.
1707
2348
 
1708
- *Guilherme Goettems Schneider*
2349
+ `authenticate_by` addresses the vulnerability by taking the same amount of
2350
+ time regardless of whether a user with a matching email is found:
1709
2351
 
1710
- * Allow generated `create_table` migrations to include or skip timestamps.
2352
+ ```ruby
2353
+ User.authenticate_by(email: "...", password: "...")
2354
+ ```
1711
2355
 
1712
- *Michael Duchemin*
2356
+ *Jonathan Hefner*
1713
2357
 
1714
2358
 
1715
- Please check [6-0-stable](https://github.com/rails/rails/blob/6-0-stable/activerecord/CHANGELOG.md) for previous changes.
2359
+ Please check [7-0-stable](https://github.com/rails/rails/blob/7-0-stable/activerecord/CHANGELOG.md) for previous changes.