activerecord 7.0.4 → 7.1.5.1

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