activerecord 7.0.4 → 7.1.3.4

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