activerecord 7.0.0 → 7.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +515 -1268
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +31 -31
  5. data/examples/performance.rb +2 -2
  6. data/lib/active_record/aggregations.rb +16 -13
  7. data/lib/active_record/association_relation.rb +2 -2
  8. data/lib/active_record/associations/alias_tracker.rb +25 -19
  9. data/lib/active_record/associations/association.rb +35 -12
  10. data/lib/active_record/associations/association_scope.rb +16 -9
  11. data/lib/active_record/associations/belongs_to_association.rb +23 -8
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
  13. data/lib/active_record/associations/builder/association.rb +3 -3
  14. data/lib/active_record/associations/builder/belongs_to.rb +22 -8
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
  16. data/lib/active_record/associations/builder/has_many.rb +3 -4
  17. data/lib/active_record/associations/builder/has_one.rb +3 -4
  18. data/lib/active_record/associations/builder/singular_association.rb +4 -0
  19. data/lib/active_record/associations/collection_association.rb +28 -17
  20. data/lib/active_record/associations/collection_proxy.rb +36 -13
  21. data/lib/active_record/associations/errors.rb +265 -0
  22. data/lib/active_record/associations/foreign_association.rb +10 -3
  23. data/lib/active_record/associations/has_many_association.rb +28 -18
  24. data/lib/active_record/associations/has_many_through_association.rb +10 -6
  25. data/lib/active_record/associations/has_one_association.rb +10 -3
  26. data/lib/active_record/associations/join_dependency/join_association.rb +27 -25
  27. data/lib/active_record/associations/join_dependency.rb +18 -14
  28. data/lib/active_record/associations/nested_error.rb +47 -0
  29. data/lib/active_record/associations/preloader/association.rb +33 -8
  30. data/lib/active_record/associations/preloader/branch.rb +7 -1
  31. data/lib/active_record/associations/preloader/through_association.rb +2 -4
  32. data/lib/active_record/associations/preloader.rb +13 -10
  33. data/lib/active_record/associations/singular_association.rb +7 -1
  34. data/lib/active_record/associations/through_association.rb +22 -11
  35. data/lib/active_record/associations.rb +378 -491
  36. data/lib/active_record/attribute_assignment.rb +1 -13
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
  38. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  39. data/lib/active_record/attribute_methods/dirty.rb +53 -35
  40. data/lib/active_record/attribute_methods/primary_key.rb +45 -25
  41. data/lib/active_record/attribute_methods/query.rb +28 -16
  42. data/lib/active_record/attribute_methods/read.rb +8 -7
  43. data/lib/active_record/attribute_methods/serialization.rb +153 -70
  44. data/lib/active_record/attribute_methods/time_zone_conversion.rb +7 -6
  45. data/lib/active_record/attribute_methods/write.rb +6 -6
  46. data/lib/active_record/attribute_methods.rb +153 -40
  47. data/lib/active_record/attributes.rb +63 -48
  48. data/lib/active_record/autosave_association.rb +70 -38
  49. data/lib/active_record/base.rb +12 -8
  50. data/lib/active_record/callbacks.rb +16 -32
  51. data/lib/active_record/coders/column_serializer.rb +61 -0
  52. data/lib/active_record/coders/json.rb +1 -1
  53. data/lib/active_record/coders/yaml_column.rb +70 -34
  54. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +124 -132
  55. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +4 -1
  57. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +297 -88
  58. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
  59. data/lib/active_record/connection_adapters/abstract/database_statements.rb +160 -45
  60. data/lib/active_record/connection_adapters/abstract/query_cache.rb +215 -63
  61. data/lib/active_record/connection_adapters/abstract/quoting.rb +83 -65
  62. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +163 -29
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +319 -135
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +367 -75
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +512 -126
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +282 -119
  70. data/lib/active_record/connection_adapters/column.rb +9 -0
  71. data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
  72. data/lib/active_record/connection_adapters/mysql/database_statements.rb +27 -140
  73. data/lib/active_record/connection_adapters/mysql/quoting.rb +64 -52
  74. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
  76. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
  77. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +45 -14
  78. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
  79. data/lib/active_record/connection_adapters/mysql2_adapter.rb +101 -68
  80. data/lib/active_record/connection_adapters/pool_config.rb +20 -10
  81. data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +16 -3
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +101 -48
  84. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  85. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -2
  87. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
  88. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
  90. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +4 -2
  91. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
  92. data/lib/active_record/connection_adapters/postgresql/quoting.rb +94 -61
  93. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +6 -10
  94. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
  95. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +151 -2
  96. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +53 -0
  97. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +379 -66
  98. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
  99. data/lib/active_record/connection_adapters/postgresql_adapter.rb +370 -203
  100. data/lib/active_record/connection_adapters/schema_cache.rb +302 -79
  101. data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
  102. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +60 -43
  103. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +61 -46
  104. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  105. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
  106. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
  107. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +64 -22
  108. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +321 -110
  109. data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
  110. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
  111. data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
  112. data/lib/active_record/connection_adapters.rb +124 -1
  113. data/lib/active_record/connection_handling.rb +98 -106
  114. data/lib/active_record/core.rb +220 -177
  115. data/lib/active_record/counter_cache.rb +68 -34
  116. data/lib/active_record/database_configurations/connection_url_resolver.rb +8 -2
  117. data/lib/active_record/database_configurations/database_config.rb +26 -5
  118. data/lib/active_record/database_configurations/hash_config.rb +52 -34
  119. data/lib/active_record/database_configurations/url_config.rb +37 -12
  120. data/lib/active_record/database_configurations.rb +88 -35
  121. data/lib/active_record/delegated_type.rb +40 -11
  122. data/lib/active_record/deprecator.rb +7 -0
  123. data/lib/active_record/destroy_association_async_job.rb +3 -1
  124. data/lib/active_record/disable_joins_association_relation.rb +1 -1
  125. data/lib/active_record/dynamic_matchers.rb +2 -2
  126. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  127. data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
  128. data/lib/active_record/encryption/config.rb +25 -1
  129. data/lib/active_record/encryption/configurable.rb +13 -14
  130. data/lib/active_record/encryption/context.rb +10 -3
  131. data/lib/active_record/encryption/contexts.rb +8 -4
  132. data/lib/active_record/encryption/derived_secret_key_provider.rb +9 -3
  133. data/lib/active_record/encryption/deterministic_key_provider.rb +1 -1
  134. data/lib/active_record/encryption/encryptable_record.rb +47 -25
  135. data/lib/active_record/encryption/encrypted_attribute_type.rb +49 -14
  136. data/lib/active_record/encryption/encryptor.rb +25 -10
  137. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +3 -3
  138. data/lib/active_record/encryption/extended_deterministic_queries.rb +83 -86
  139. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
  140. data/lib/active_record/encryption/key_generator.rb +12 -1
  141. data/lib/active_record/encryption/message.rb +1 -1
  142. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  143. data/lib/active_record/encryption/message_serializer.rb +6 -0
  144. data/lib/active_record/encryption/null_encryptor.rb +4 -0
  145. data/lib/active_record/encryption/properties.rb +4 -4
  146. data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
  147. data/lib/active_record/encryption/scheme.rb +23 -22
  148. data/lib/active_record/encryption.rb +1 -0
  149. data/lib/active_record/enum.rb +131 -27
  150. data/lib/active_record/errors.rb +151 -31
  151. data/lib/active_record/explain.rb +21 -12
  152. data/lib/active_record/explain_subscriber.rb +1 -1
  153. data/lib/active_record/fixture_set/model_metadata.rb +14 -4
  154. data/lib/active_record/fixture_set/render_context.rb +2 -0
  155. data/lib/active_record/fixture_set/table_row.rb +29 -8
  156. data/lib/active_record/fixtures.rb +169 -99
  157. data/lib/active_record/future_result.rb +47 -8
  158. data/lib/active_record/gem_version.rb +3 -3
  159. data/lib/active_record/inheritance.rb +34 -18
  160. data/lib/active_record/insert_all.rb +72 -22
  161. data/lib/active_record/integration.rb +13 -10
  162. data/lib/active_record/internal_metadata.rb +124 -20
  163. data/lib/active_record/locking/optimistic.rb +39 -24
  164. data/lib/active_record/locking/pessimistic.rb +8 -5
  165. data/lib/active_record/log_subscriber.rb +28 -27
  166. data/lib/active_record/marshalling.rb +56 -0
  167. data/lib/active_record/message_pack.rb +124 -0
  168. data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
  169. data/lib/active_record/middleware/database_selector.rb +18 -13
  170. data/lib/active_record/middleware/shard_selector.rb +7 -5
  171. data/lib/active_record/migration/command_recorder.rb +110 -13
  172. data/lib/active_record/migration/compatibility.rb +174 -64
  173. data/lib/active_record/migration/default_strategy.rb +22 -0
  174. data/lib/active_record/migration/execution_strategy.rb +19 -0
  175. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  176. data/lib/active_record/migration.rb +292 -125
  177. data/lib/active_record/model_schema.rb +113 -112
  178. data/lib/active_record/nested_attributes.rb +35 -9
  179. data/lib/active_record/normalization.rb +163 -0
  180. data/lib/active_record/persistence.rb +177 -345
  181. data/lib/active_record/promise.rb +84 -0
  182. data/lib/active_record/query_cache.rb +19 -25
  183. data/lib/active_record/query_logs.rb +102 -51
  184. data/lib/active_record/query_logs_formatter.rb +41 -0
  185. data/lib/active_record/querying.rb +34 -9
  186. data/lib/active_record/railtie.rb +153 -100
  187. data/lib/active_record/railties/controller_runtime.rb +24 -10
  188. data/lib/active_record/railties/databases.rake +148 -152
  189. data/lib/active_record/railties/job_runtime.rb +23 -0
  190. data/lib/active_record/readonly_attributes.rb +32 -5
  191. data/lib/active_record/reflection.rb +278 -69
  192. data/lib/active_record/relation/batches/batch_enumerator.rb +20 -5
  193. data/lib/active_record/relation/batches.rb +198 -63
  194. data/lib/active_record/relation/calculations.rb +293 -108
  195. data/lib/active_record/relation/delegation.rb +31 -20
  196. data/lib/active_record/relation/finder_methods.rb +93 -18
  197. data/lib/active_record/relation/merger.rb +6 -6
  198. data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
  199. data/lib/active_record/relation/predicate_builder/association_query_value.rb +38 -4
  200. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
  201. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  202. data/lib/active_record/relation/predicate_builder.rb +28 -16
  203. data/lib/active_record/relation/query_attribute.rb +25 -1
  204. data/lib/active_record/relation/query_methods.rb +625 -107
  205. data/lib/active_record/relation/record_fetch_warning.rb +3 -0
  206. data/lib/active_record/relation/spawn_methods.rb +5 -4
  207. data/lib/active_record/relation/where_clause.rb +7 -19
  208. data/lib/active_record/relation.rb +602 -96
  209. data/lib/active_record/result.rb +55 -52
  210. data/lib/active_record/runtime_registry.rb +63 -1
  211. data/lib/active_record/sanitization.rb +76 -30
  212. data/lib/active_record/schema.rb +39 -23
  213. data/lib/active_record/schema_dumper.rb +82 -30
  214. data/lib/active_record/schema_migration.rb +75 -24
  215. data/lib/active_record/scoping/default.rb +20 -12
  216. data/lib/active_record/scoping/named.rb +3 -2
  217. data/lib/active_record/scoping.rb +2 -1
  218. data/lib/active_record/secure_password.rb +60 -0
  219. data/lib/active_record/secure_token.rb +21 -3
  220. data/lib/active_record/serialization.rb +5 -0
  221. data/lib/active_record/signed_id.rb +29 -8
  222. data/lib/active_record/statement_cache.rb +7 -7
  223. data/lib/active_record/store.rb +16 -11
  224. data/lib/active_record/suppressor.rb +3 -1
  225. data/lib/active_record/table_metadata.rb +7 -3
  226. data/lib/active_record/tasks/database_tasks.rb +191 -121
  227. data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
  228. data/lib/active_record/tasks/postgresql_database_tasks.rb +17 -15
  229. data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -7
  230. data/lib/active_record/test_fixtures.rb +174 -152
  231. data/lib/active_record/testing/query_assertions.rb +121 -0
  232. data/lib/active_record/timestamp.rb +31 -17
  233. data/lib/active_record/token_for.rb +123 -0
  234. data/lib/active_record/touch_later.rb +12 -7
  235. data/lib/active_record/transaction.rb +132 -0
  236. data/lib/active_record/transactions.rb +109 -27
  237. data/lib/active_record/translation.rb +1 -3
  238. data/lib/active_record/type/adapter_specific_registry.rb +1 -8
  239. data/lib/active_record/type/internal/timezone.rb +7 -2
  240. data/lib/active_record/type/serialized.rb +9 -7
  241. data/lib/active_record/type/time.rb +4 -0
  242. data/lib/active_record/type_caster/connection.rb +4 -4
  243. data/lib/active_record/validations/absence.rb +1 -1
  244. data/lib/active_record/validations/associated.rb +12 -6
  245. data/lib/active_record/validations/numericality.rb +5 -4
  246. data/lib/active_record/validations/presence.rb +5 -28
  247. data/lib/active_record/validations/uniqueness.rb +63 -14
  248. data/lib/active_record/validations.rb +12 -5
  249. data/lib/active_record/version.rb +1 -1
  250. data/lib/active_record.rb +266 -30
  251. data/lib/arel/alias_predication.rb +1 -1
  252. data/lib/arel/collectors/bind.rb +2 -0
  253. data/lib/arel/collectors/composite.rb +7 -0
  254. data/lib/arel/collectors/sql_string.rb +1 -1
  255. data/lib/arel/collectors/substitute_binds.rb +1 -1
  256. data/lib/arel/errors.rb +10 -0
  257. data/lib/arel/factory_methods.rb +4 -0
  258. data/lib/arel/filter_predications.rb +1 -1
  259. data/lib/arel/nodes/binary.rb +6 -7
  260. data/lib/arel/nodes/bound_sql_literal.rb +65 -0
  261. data/lib/arel/nodes/cte.rb +36 -0
  262. data/lib/arel/nodes/filter.rb +1 -1
  263. data/lib/arel/nodes/fragments.rb +35 -0
  264. data/lib/arel/nodes/homogeneous_in.rb +1 -9
  265. data/lib/arel/nodes/leading_join.rb +8 -0
  266. data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
  267. data/lib/arel/nodes/node.rb +115 -5
  268. data/lib/arel/nodes/sql_literal.rb +13 -0
  269. data/lib/arel/nodes/table_alias.rb +4 -0
  270. data/lib/arel/nodes.rb +6 -2
  271. data/lib/arel/predications.rb +3 -1
  272. data/lib/arel/select_manager.rb +1 -1
  273. data/lib/arel/table.rb +9 -5
  274. data/lib/arel/tree_manager.rb +8 -3
  275. data/lib/arel/update_manager.rb +2 -1
  276. data/lib/arel/visitors/dot.rb +1 -0
  277. data/lib/arel/visitors/mysql.rb +17 -5
  278. data/lib/arel/visitors/postgresql.rb +1 -12
  279. data/lib/arel/visitors/to_sql.rb +112 -34
  280. data/lib/arel/visitors/visitor.rb +2 -2
  281. data/lib/arel.rb +21 -3
  282. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  283. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
  284. data/lib/rails/generators/active_record/migration.rb +3 -1
  285. data/lib/rails/generators/active_record/model/USAGE +113 -0
  286. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  287. metadata +59 -17
  288. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  289. data/lib/active_record/null_relation.rb +0 -63
data/CHANGELOG.md CHANGED
@@ -1,1697 +1,944 @@
1
- ## Rails 7.0.0 (December 15, 2021) ##
1
+ ## Rails 7.2.1 (August 22, 2024) ##
2
2
 
3
- * Better handle SQL queries with invalid encoding.
4
-
5
- ```ruby
6
- Post.create(name: "broken \xC8 UTF-8")
7
- ```
8
-
9
- Would cause all adapters to fail in a non controlled way in the code
10
- responsible to detect write queries.
11
-
12
- The query is now properly passed to the database connection, which might or might
13
- not be able to handle it, but will either succeed or failed in a more correct way.
14
-
15
- *Jean Boussier*
16
-
17
- * Move database and shard selection config options to a generator.
18
-
19
- 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.
20
-
21
- *Eileen M. Uchitelle*
22
-
23
- ## Rails 7.0.0.rc3 (December 14, 2021) ##
24
-
25
- * No changes.
26
-
27
-
28
- ## Rails 7.0.0.rc2 (December 14, 2021) ##
29
-
30
- * No changes.
31
-
32
- ## Rails 7.0.0.rc1 (December 06, 2021) ##
33
-
34
- * Remove deprecated `ActiveRecord::DatabaseConfigurations::DatabaseConfig#spec_name`.
35
-
36
- *Rafael Mendonça França*
37
-
38
- * Remove deprecated `ActiveRecord::Connection#in_clause_length`.
39
-
40
- *Rafael Mendonça França*
41
-
42
- * Remove deprecated `ActiveRecord::Connection#allowed_index_name_length`.
3
+ * Fix detection for `enum` columns with parallelized tests and PostgreSQL.
43
4
 
44
5
  *Rafael Mendonça França*
45
6
 
46
- * Remove deprecated `ActiveRecord::Base#remove_connection`.
47
-
48
- *Rafael Mendonça França*
49
-
50
- * Load STI Models in fixtures
51
-
52
- Data from Fixtures now loads based on the specific class for models with
53
- Single Table Inheritance. This affects enums defined in subclasses, previously
54
- the value of these fields was not parsed and remained `nil`
55
-
56
- *Andres Howard*
57
-
58
- * `#authenticate` returns false when the password is blank instead of raising an error.
59
-
60
- *Muhammad Muhammad Ibrahim*
7
+ * Allow to eager load nested nil associations.
61
8
 
62
- * Fix `ActiveRecord::QueryMethods#in_order_of` behavior for integer enums.
63
-
64
- `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.
65
-
66
- The following example now works as expected:
67
-
68
- ```ruby
69
- class Book < ApplicationRecord
70
- enum status: [:proposed, :written, :published]
71
- end
72
-
73
- Book.in_order_of(:status, %w[written published proposed])
74
- ```
75
-
76
- *Alexandre Ruban*
77
-
78
- * Ignore persisted in-memory records when merging target lists.
79
-
80
- *Kevin Sjöberg*
81
-
82
- * Add a new option `:update_only` to `upsert_all` to configure the list of columns to update in case of conflict.
83
-
84
- 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:
85
-
86
- ```ruby
87
- Commodity.upsert_all(
88
- [
89
- { id: 2, name: "Copper", price: 4.84 },
90
- { id: 4, name: "Gold", price: 1380.87 },
91
- { id: 6, name: "Aluminium", price: 0.35 }
92
- ],
93
- update_only: [:price] # Only prices will be updated
94
- )
95
- ```
9
+ *fatkodima*
96
10
 
97
- *Jorge Manrubia*
11
+ * Fix swallowing ignore order warning when batching using `BatchEnumerator`.
98
12
 
99
- * Remove deprecated `ActiveRecord::Result#map!` and `ActiveRecord::Result#collect!`.
13
+ *fatkodima*
100
14
 
101
- *Rafael Mendonça França*
15
+ * Fix memory bloat on the connection pool when using the Fiber `IsolatedExecutionState`.
102
16
 
103
- * Remove deprecated `ActiveRecord::Base.configurations.to_h`.
17
+ *Jean Boussier*
104
18
 
105
- *Rafael Mendonça França*
19
+ * Restore inferred association class with the same modularized name.
106
20
 
107
- * Remove deprecated `ActiveRecord::Base.configurations.default_hash`.
21
+ *Justin Ko*
108
22
 
109
- *Rafael Mendonça França*
23
+ * Fix `ActiveRecord::Base.inspect` to properly explain how to load schema information.
110
24
 
111
- * Remove deprecated `ActiveRecord::Base.arel_attribute`.
25
+ *Jean Boussier*
112
26
 
113
- *Rafael Mendonça França*
27
+ * Check invalid `enum` options for the new syntax.
114
28
 
115
- * Remove deprecated `ActiveRecord::Base.connection_config`.
29
+ The options using `_` prefix in the old syntax are invalid in the new syntax.
116
30
 
117
31
  *Rafael Mendonça França*
118
32
 
119
- * Filter attributes in SQL logs
120
-
121
- Previously, SQL queries in logs containing `ActiveRecord::Base.filter_attributes` were not filtered.
122
-
123
- Now, the filter attributes will be masked `[FILTERED]` in the logs when `prepared_statement` is enabled.
33
+ * Fix `ActiveRecord::Encryption::EncryptedAttributeType#type` to return
34
+ actual cast type.
124
35
 
125
- ```
126
- # Before:
127
- Foo Load (0.2ms) SELECT "foos".* FROM "foos" WHERE "foos"."passw" = ? LIMIT ? [["passw", "hello"], ["LIMIT", 1]]
128
-
129
- # After:
130
- Foo Load (0.5ms) SELECT "foos".* FROM "foos" WHERE "foos"."passw" = ? LIMIT ? [["passw", "[FILTERED]"], ["LIMIT", 1]]
131
- ```
36
+ *Vasiliy Ermolovich*
132
37
 
133
- *Aishwarya Subramanian*
38
+ * Fix `create_table` with `:auto_increment` option for MySQL adapter.
134
39
 
135
- * Remove deprecated `Tasks::DatabaseTasks.spec`.
136
-
137
- *Rafael Mendonça França*
40
+ *fatkodima*
138
41
 
139
- * Remove deprecated `Tasks::DatabaseTasks.current_config`.
140
42
 
141
- *Rafael Mendonça França*
43
+ ## Rails 7.2.0 (August 09, 2024) ##
142
44
 
143
- * Deprecate `Tasks::DatabaseTasks.schema_file_type`.
45
+ * Handle commas in Sqlite3 default function definitions.
144
46
 
145
- *Rafael Mendonça França*
47
+ *Stephen Margheim*
146
48
 
147
- * Remove deprecated `Tasks::DatabaseTasks.dump_filename`.
49
+ * Fixes `validates_associated` raising an exception when configured with a
50
+ singular association and having `index_nested_attribute_errors` enabled.
148
51
 
149
- *Rafael Mendonça França*
52
+ *Martin Spickermann*
150
53
 
151
- * Remove deprecated `Tasks::DatabaseTasks.schema_file`.
54
+ * The constant `ActiveRecord::ImmutableRelation` has been deprecated because
55
+ we want to reserve that name for a stronger sense of "immutable relation".
56
+ Please use `ActiveRecord::UnmodifiableRelation` instead.
152
57
 
153
- *Rafael Mendonça França*
58
+ *Xavier Noria*
154
59
 
155
- * Remove deprecated `environment` and `name` arguments from `Tasks::DatabaseTasks.schema_up_to_date?`.
60
+ * Add condensed `#inspect` for `ConnectionPool`, `AbstractAdapter`, and
61
+ `DatabaseConfig`.
156
62
 
157
- *Rafael Mendonça França*
63
+ *Hartley McGuire*
158
64
 
159
- * Merging conditions on the same column no longer maintain both conditions,
160
- and will be consistently replaced by the latter condition.
65
+ * Fixed a memory performance issue in Active Record attribute methods definition.
161
66
 
162
- ```ruby
163
- # Rails 6.1 (IN clause is replaced by merger side equality condition)
164
- Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob]
165
- # Rails 6.1 (both conflict conditions exists, deprecated)
166
- Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => []
167
- # Rails 6.1 with rewhere to migrate to Rails 7.0's behavior
168
- Author.where(id: david.id..mary.id).merge(Author.where(id: bob), rewhere: true) # => [bob]
169
- # Rails 7.0 (same behavior with IN clause, mergee side condition is consistently replaced)
170
- Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob]
171
- Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => [bob]
67
+ *Jean Boussier*
172
68
 
173
- *Rafael Mendonça França*
69
+ * Define the new Active Support notification event `start_transaction.active_record`.
174
70
 
175
- * Remove deprecated support to `Model.reorder(nil).first` to search using non-deterministic order.
71
+ This event is fired when database transactions or savepoints start, and
72
+ complements `transaction.active_record`, which is emitted when they finish.
176
73
 
177
- *Rafael Mendonça França*
74
+ The payload has the transaction (`:transaction`) and the connection (`:connection`).
178
75
 
179
- * Remove deprecated rake tasks:
76
+ *Xavier Noria*
180
77
 
181
- * `db:schema:load_if_ruby`
182
- * `db:structure:dump`
183
- * `db:structure:load`
184
- * `db:structure:load_if_sql`
185
- * `db:structure:dump:#{name}`
186
- * `db:structure:load:#{name}`
187
- * `db:test:load_structure`
188
- * `db:test:load_structure:#{name}`
78
+ * Fix an issue where the IDs reader method did not return expected results
79
+ for preloaded associations in models using composite primary keys.
189
80
 
190
- *Rafael Mendonça França*
81
+ *Jay Ang*
191
82
 
192
- * Remove deprecated `DatabaseConfig#config` method.
83
+ * The payload of `sql.active_record` Active Support notifications now has the current transaction in the `:transaction` key.
193
84
 
194
- *Rafael Mendonça França*
85
+ *Xavier Noria*
195
86
 
196
- * Rollback transactions when the block returns earlier than expected.
87
+ * The payload of `transaction.active_record` Active Support notifications now has the transaction the event is related to in the `:transaction` key.
197
88
 
198
- Before this change, when a transaction block returned early, the transaction would be committed.
89
+ *Xavier Noria*
199
90
 
200
- The problem is that timeouts triggered inside the transaction block was also making the incomplete transaction
201
- to be committed, so in order to avoid this mistake, the transaction block is rolled back.
91
+ * Define `ActiveRecord::Transaction#uuid`, which returns a UUID for the database transaction. This may be helpful when tracing database activity. These UUIDs are generated only on demand.
202
92
 
203
- *Rafael Mendonça França*
93
+ *Xavier Noria*
204
94
 
205
- * Add middleware for automatic shard swapping.
95
+ * Fix inference of association model on nested models with the same demodularized name.
206
96
 
207
- 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:
97
+ E.g. with the following setup:
208
98
 
209
99
  ```ruby
210
- config.active_record.shard_resolver = ->(request) {
211
- subdomain = request.subdomain
212
- tenant = Tenant.find_by_subdomain!(subdomain)
213
- tenant.shard
214
- }
100
+ class Nested::Post < ApplicationRecord
101
+ has_one :post, through: :other
102
+ end
215
103
  ```
216
104
 
217
- See guides for more details.
218
-
219
- *Eileen M. Uchitelle*, *John Crepezzi*
220
-
221
- * Remove deprecated support to pass a column to `type_cast`.
222
-
223
- *Rafael Mendonça França*
224
-
225
- * Remove deprecated support to type cast to database values `ActiveRecord::Base` objects.
226
-
227
- *Rafael Mendonça França*
105
+ Before, `#post` would infer the model as `Nested::Post`, but now it correctly infers `Post`.
228
106
 
229
- * Remove deprecated support to quote `ActiveRecord::Base` objects.
107
+ *Joshua Young*
230
108
 
231
- *Rafael Mendonça França*
109
+ * PostgreSQL `Cidr#change?` detects the address prefix change.
232
110
 
233
- * Remove deprecacated support to resolve connection using `"primary"` as connection specification name.
111
+ *Taketo Takashima*
234
112
 
235
- *Rafael Mendonça França*
113
+ * Change `BatchEnumerator#destroy_all` to return the total number of affected rows.
236
114
 
237
- * Remove deprecation warning when using `:interval` column is used in PostgreSQL database.
115
+ Previously, it always returned `nil`.
238
116
 
239
- Now, interval columns will return `ActiveSupport::Duration` objects instead of strings.
117
+ *fatkodima*
240
118
 
241
- To keep the old behavior, you can add this line to your model:
119
+ * Support `touch_all` in batches.
242
120
 
243
121
  ```ruby
244
- attribute :column, :string
122
+ Post.in_batches.touch_all
245
123
  ```
246
124
 
247
- *Rafael Mendonça França*
125
+ *fatkodima*
248
126
 
249
- * Remove deprecated support to YAML load `ActiveRecord::Base` instance in the Rails 4.2 and 4.1 formats.
127
+ * Add support for `:if_not_exists` and `:force` options to `create_schema`.
250
128
 
251
- *Rafael Mendonça França*
129
+ *fatkodima*
252
130
 
253
- * Remove deprecated option `:spec_name` in the `configs_for` method.
131
+ * Fix `index_errors` having incorrect index in association validation errors.
254
132
 
255
- *Rafael Mendonça França*
133
+ *lulalala*
256
134
 
257
- * Remove deprecated `ActiveRecord::Base.allow_unsafe_raw_sql`.
135
+ * Add `index_errors: :nested_attributes_order` mode.
258
136
 
259
- *Rafael Mendonça França*
137
+ This indexes the association validation errors based on the order received by nested attributes setter, and respects the `reject_if` configuration. This enables API to provide enough information to the frontend to map the validation errors back to their respective form fields.
260
138
 
261
- * Fix regression bug that caused ignoring additional conditions for preloading has_many-through relations.
139
+ *lulalala*
262
140
 
263
- Fixes #43132
141
+ * Add `Rails.application.config.active_record.postgresql_adapter_decode_dates` to opt out of decoding dates automatically with the postgresql adapter. Defaults to true.
264
142
 
265
- *Alexander Pauly*
143
+ *Joé Dupuis*
266
144
 
267
- * Fix `has_many` inversing recursion on models with recursive associations.
145
+ * Association option `query_constraints` is deprecated in favor of `foreign_key`.
268
146
 
269
- *Gannon McGibbon*
147
+ *Nikita Vasilevsky*
270
148
 
271
- * Add `accepts_nested_attributes_for` support for `delegated_type`
149
+ * Add `ENV["SKIP_TEST_DATABASE_TRUNCATE"]` flag to speed up multi-process test runs on large DBs when all tests run within default transaction.
272
150
 
273
- ```ruby
274
- class Entry < ApplicationRecord
275
- delegated_type :entryable, types: %w[ Message Comment ]
276
- accepts_nested_attributes_for :entryable
277
- end
151
+ This cuts ~10s from the test run of HEY when run by 24 processes against the 178 tables, since ~4,000 table truncates can then be skipped.
278
152
 
279
- entry = Entry.create(entryable_type: 'Message', entryable_attributes: { content: 'Hello world' })
280
- # => #<Entry:0x00>
281
- # id: 1
282
- # entryable_id: 1,
283
- # entryable_type: 'Message'
284
- # ...>
285
-
286
- entry.entryable
287
- # => #<Message:0x01>
288
- # id: 1
289
- # content: 'Hello world'
290
- # ...>
291
- ```
153
+ *DHH*
292
154
 
293
- Previously it would raise an error:
155
+ * Added support for recursive common table expressions.
294
156
 
295
157
  ```ruby
296
- Entry.create(entryable_type: 'Message', entryable_attributes: { content: 'Hello world' })
297
- # ArgumentError: Cannot build association `entryable'. Are you trying to build a polymorphic one-to-one association?
298
- ```
299
-
300
- *Sjors Baltus*
301
-
302
- * Use subquery for DELETE with GROUP_BY and HAVING clauses.
303
-
304
- Prior to this change, deletes with GROUP_BY and HAVING were returning an error.
305
-
306
- After this change, GROUP_BY and HAVING are valid clauses in DELETE queries, generating the following query:
307
-
308
- ```sql
309
- DELETE FROM "posts" WHERE "posts"."id" IN (
310
- SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id" GROUP BY "posts"."id" HAVING (count(comments.id) >= 2))
311
- ) [["flagged", "t"]]
312
- ```
313
-
314
- *Ignacio Chiazzo Cardarello*
315
-
316
- * Use subquery for UPDATE with GROUP_BY and HAVING clauses.
317
-
318
- Prior to this change, updates with GROUP_BY and HAVING were being ignored, generating a SQL like this:
319
-
320
- ```sql
321
- UPDATE "posts" SET "flagged" = ? WHERE "posts"."id" IN (
322
- SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"
323
- ) [["flagged", "t"]]
158
+ Post.with_recursive(
159
+ post_and_replies: [
160
+ Post.where(id: 42),
161
+ Post.joins('JOIN post_and_replies ON posts.in_reply_to_id = post_and_replies.id'),
162
+ ]
163
+ )
324
164
  ```
325
165
 
326
- After this change, GROUP_BY and HAVING clauses are used as a subquery in updates, like this:
166
+ Generates the following SQL:
327
167
 
328
168
  ```sql
329
- UPDATE "posts" SET "flagged" = ? WHERE "posts"."id" IN (
330
- SELECT "posts"."id" FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"
331
- GROUP BY posts.id HAVING (count(comments.id) >= 2)
332
- ) [["flagged", "t"]]
333
- ```
334
-
335
- *Ignacio Chiazzo Cardarello*
336
-
337
- * Add support for setting the filename of the schema or structure dump in the database config.
338
-
339
- Applications may now set their the filename or path of the schema / structure dump file in their database configuration.
340
-
341
- ```yaml
342
- production:
343
- primary:
344
- database: my_db
345
- schema_dump: my_schema_dump_filename.rb
346
- animals:
347
- database: animals_db
348
- schema_dump: false
169
+ WITH RECURSIVE "post_and_replies" AS (
170
+ (SELECT "posts".* FROM "posts" WHERE "posts"."id" = 42)
171
+ UNION ALL
172
+ (SELECT "posts".* FROM "posts" JOIN post_and_replies ON posts.in_reply_to_id = post_and_replies.id)
173
+ )
174
+ SELECT "posts".* FROM "posts"
349
175
  ```
350
176
 
351
- 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`.
352
-
353
- *Eileen M. Uchitelle*, *Ryan Kerr*
354
-
355
- * Add `ActiveRecord::Base.prohibit_shard_swapping` to prevent attempts to change the shard within a block.
177
+ *ClearlyClaire*
356
178
 
357
- *John Crepezzi*, *Eileen M. Uchitelle*
358
-
359
- * Filter unchanged attributes with default function from insert query when `partial_inserts` is disabled.
360
-
361
- *Akshay Birajdar*, *Jacopo Beschi*
362
-
363
- * Add support for FILTER clause (SQL:2003) to Arel.
364
-
365
- Currently supported by PostgreSQL 9.4+ and SQLite 3.30+.
366
-
367
- *Andrey Novikov*
368
-
369
- * Automatically set timestamps on record creation during bulk insert/upsert
370
-
371
- 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}`).
372
-
373
- 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.
374
-
375
- Note that this means `upsert_all` on models with `record_timestamps = false` will no longer touch `updated_{at,on}` automatically.
376
-
377
- *Sam Bostock*
378
-
379
- * Don't require `role` when passing `shard` to `connected_to`.
380
-
381
- `connected_to` can now be called with a `shard` only. Note that `role` is still inherited if `connected_to` calls are nested.
382
-
383
- *Eileen M. Uchitelle*
384
-
385
- * Add option to lazily load the schema cache on the connection.
386
-
387
- 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.
388
-
389
- 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.
390
-
391
- *Eileen M. Uchitelle*
392
-
393
- * Allow automatic `inverse_of` detection for associations with scopes.
394
-
395
- Automatic `inverse_of` detection now works for associations with scopes. For
396
- example, the `comments` association here now automatically detects
397
- `inverse_of: :post`, so we don't need to pass that option:
179
+ * `validate_constraint` can be called in a `change_table` block.
398
180
 
181
+ ex:
399
182
  ```ruby
400
- class Post < ActiveRecord::Base
401
- has_many :comments, -> { visible }
402
- end
403
-
404
- class Comment < ActiveRecord::Base
405
- belongs_to :post
183
+ change_table :products do |t|
184
+ t.check_constraint "price > discounted_price", name: "price_check", validate: false
185
+ t.validate_check_constraint "price_check"
406
186
  end
407
187
  ```
408
188
 
409
- Note that the automatic detection still won't work if the inverse
410
- association has a scope. In this example a scope on the `post` association
411
- would still prevent Rails from finding the inverse for the `comments`
412
- association.
189
+ *Cody Cutrer*
413
190
 
414
- This will be the default for new apps in Rails 7. To opt in:
191
+ * `PostgreSQLAdapter` now decodes columns of type date to `Date` instead of string.
415
192
 
193
+ Ex:
416
194
  ```ruby
417
- config.active_record.automatic_scope_inversing = true
195
+ ActiveRecord::Base.connection
196
+ .select_value("select '2024-01-01'::date").class #=> Date
418
197
  ```
419
198
 
420
- *Daniel Colson*, *Chris Bloom*
421
-
422
- * Accept optional transaction args to `ActiveRecord::Locking::Pessimistic#with_lock`
199
+ *Joé Dupuis*
423
200
 
424
- `#with_lock` now accepts transaction options like `requires_new:`,
425
- `isolation:`, and `joinable:`
201
+ * Strict loading using `:n_plus_one_only` does not eagerly load child associations.
426
202
 
427
- *John Mileham*
203
+ With this change, child associations are no longer eagerly loaded, to
204
+ match intended behavior and to prevent non-deterministic order issues caused
205
+ by calling methods like `first` or `last`. As `first` and `last` don't cause
206
+ an N+1 by themselves, calling child associations will no longer raise.
207
+ Fixes #49473.
428
208
 
429
- * Adds support for deferrable foreign key constraints in PostgreSQL.
430
-
431
- By default, foreign key constraints in PostgreSQL are checked after each statement. This works for most use cases,
432
- but becomes a major limitation when creating related records before the parent record is inserted into the database.
433
- One example of this is looking up / creating a person via one or more unique alias.
209
+ Before:
434
210
 
435
211
  ```ruby
436
- Person.transaction do
437
- alias = Alias
438
- .create_with(user_id: SecureRandom.uuid)
439
- .create_or_find_by(name: "DHH")
440
-
441
- person = Person
442
- .create_with(name: "David Heinemeier Hansson")
443
- .create_or_find_by(id: alias.user_id)
444
- end
212
+ person = Person.find(1)
213
+ person.strict_loading!(mode: :n_plus_one_only)
214
+ person.posts.first
215
+ # SELECT * FROM posts WHERE person_id = 1; -- non-deterministic order
216
+ person.posts.first.firm # raises ActiveRecord::StrictLoadingViolationError
445
217
  ```
446
218
 
447
- Using the default behavior, the transaction would fail when executing the first `INSERT` statement.
448
-
449
- By passing the `:deferrable` option to the `add_foreign_key` statement in migrations, it's possible to defer this
450
- check.
219
+ After:
451
220
 
452
221
  ```ruby
453
- add_foreign_key :aliases, :person, deferrable: true
222
+ person = Person.find(1)
223
+ person.strict_loading!(mode: :n_plus_one_only)
224
+ person.posts.first # this is 1+1, not N+1
225
+ # SELECT * FROM posts WHERE person_id = 1 ORDER BY id LIMIT 1;
226
+ person.posts.first.firm # no longer raises
454
227
  ```
455
228
 
456
- Passing `deferrable: true` doesn't change the default behavior, but allows manually deferring the check using
457
- `SET CONSTRAINTS ALL DEFERRED` within a transaction. This will cause the foreign keys to be checked after the
458
- transaction.
459
-
460
- It's also possible to adjust the default behavior from an immediate check (after the statement), to a deferred check
461
- (after the transaction):
229
+ *Reid Lynch*
462
230
 
463
- ```ruby
464
- add_foreign_key :aliases, :person, deferrable: :deferred
465
- ```
231
+ * Allow `Sqlite3Adapter` to use `sqlite3` gem version `2.x`.
466
232
 
467
- *Benedikt Deicke*
233
+ *Mike Dalessio*
468
234
 
469
- * Allow configuring Postgres password through the socket URL.
235
+ * Allow `ActiveRecord::Base#pluck` to accept hash values.
470
236
 
471
- For example:
472
237
  ```ruby
473
- ActiveRecord::DatabaseConfigurations::UrlConfig.new(
474
- :production, :production, 'postgres:///?user=user&password=secret&dbname=app', {}
475
- ).configuration_hash
238
+ # Before
239
+ Post.joins(:comments).pluck("posts.id", "comments.id", "comments.body")
240
+
241
+ # After
242
+ Post.joins(:comments).pluck(posts: [:id], comments: [:id, :body])
476
243
  ```
477
244
 
478
- will now return,
245
+ *fatkodima*
479
246
 
480
- ```ruby
481
- { :user=>"user", :password=>"secret", :dbname=>"app", :adapter=>"postgresql" }
482
- ```
247
+ * Raise an `ActiveRecord::ActiveRecordError` error when the MySQL database returns an invalid version string.
483
248
 
484
- *Abeid Ahmed*
249
+ *Kevin McPhillips*
485
250
 
486
- * PostgreSQL: support custom enum types
251
+ * `ActiveRecord::Base.transaction` now yields an `ActiveRecord::Transaction` object.
487
252
 
488
- In migrations, use `create_enum` to add a new enum type, and `t.enum` to add a column.
253
+ This allows to register callbacks on it.
489
254
 
490
255
  ```ruby
491
- def up
492
- create_enum :mood, ["happy", "sad"]
493
-
494
- change_table :cats do |t|
495
- t.enum :current_mood, enum_type: "mood", default: "happy", null: false
256
+ Article.transaction do |transaction|
257
+ article.update(published: true)
258
+ transaction.after_commit do
259
+ PublishNotificationMailer.with(article: article).deliver_later
496
260
  end
497
261
  end
498
262
  ```
499
263
 
500
- Enums will be presented correctly in `schema.rb`. Note that this is only supported by
501
- the PostgreSQL adapter.
502
-
503
- *Alex Ghiculescu*
504
-
505
- * Avoid COMMENT statements in PostgreSQL structure dumps
506
-
507
- COMMENT statements are now omitted from the output of `db:structure:dump` when using PostgreSQL >= 11.
508
- This allows loading the dump without a pgsql superuser account.
509
-
510
- Fixes #36816, #43107.
511
-
512
- *Janosch Müller*
264
+ *Jean Boussier*
513
265
 
514
- * Add support for generated columns in PostgreSQL adapter
266
+ * Add `ActiveRecord::Base.current_transaction`.
515
267
 
516
- Generated columns are supported since version 12.0 of PostgreSQL. This adds
517
- support of those to the PostgreSQL adapter.
268
+ Returns the current transaction, to allow registering callbacks on it.
518
269
 
519
270
  ```ruby
520
- create_table :users do |t|
521
- t.string :name
522
- t.virtual :name_upcased, type: :string, as: 'upper(name)', stored: true
271
+ Article.current_transaction.after_commit do
272
+ PublishNotificationMailer.with(article: article).deliver_later
523
273
  end
524
274
  ```
525
275
 
526
- *Michał Begejowicz*
527
-
528
-
529
- ## Rails 7.0.0.alpha2 (September 15, 2021) ##
530
-
531
- * No changes.
532
-
533
-
534
- ## Rails 7.0.0.alpha1 (September 15, 2021) ##
535
-
536
- * Remove warning when overwriting existing scopes
537
-
538
- Removes the following unnecessary warning message that appeared when overwriting existing scopes
539
-
540
- ```
541
- Creating scope :my_scope_name. Overwriting existing method "MyClass.my_scope_name" when overwriting existing scopes
542
- ```
543
-
544
- *Weston Ganger*
545
-
546
- * Use full precision for `updated_at` in `insert_all`/`upsert_all`
547
-
548
- `CURRENT_TIMESTAMP` provides differing precision depending on the database,
549
- and not all databases support explicitly specifying additional precision.
550
-
551
- Instead, we delegate to the new `connection.high_precision_current_timestamp`
552
- for the SQL to produce a high precision timestamp on the current database.
553
-
554
- Fixes #42992
555
-
556
- *Sam Bostock*
557
-
558
- * Add ssl support for postgresql database tasks
559
-
560
- Add `PGSSLMODE`, `PGSSLCERT`, `PGSSLKEY` and `PGSSLROOTCERT` to pg_env from database config
561
- when running postgresql database tasks.
562
-
563
- ```yaml
564
- # config/database.yml
565
-
566
- production:
567
- sslmode: verify-full
568
- sslcert: client.crt
569
- sslkey: client.key
570
- sslrootcert: ca.crt
571
- ```
572
-
573
- Environment variables
574
-
575
- ```
576
- PGSSLMODE=verify-full
577
- PGSSLCERT=client.crt
578
- PGSSLKEY=client.key
579
- PGSSLROOTCERT=ca.crt
580
- ```
581
-
582
- Fixes #42994
583
-
584
- *Michael Bayucot*
585
-
586
- * Avoid scoping update callbacks in `ActiveRecord::Relation#update!`.
587
-
588
- Making it consistent with how scoping is applied only to the query in `ActiveRecord::Relation#update`
589
- and not also to the callbacks from the update itself.
590
-
591
- *Dylan Thacker-Smith*
592
-
593
- * Fix 2 cases that inferred polymorphic class from the association's `foreign_type`
594
- using `String#constantize` instead of the model's `polymorphic_class_for`.
595
-
596
- When updating a polymorphic association, the old `foreign_type` was not inferred correctly when:
597
- 1. `touch`ing the previously associated record
598
- 2. updating the previously associated record's `counter_cache`
599
-
600
- *Jimmy Bourassa*
601
-
602
- * Add config option for ignoring tables when dumping the schema cache.
276
+ *Jean Boussier*
603
277
 
604
- Applications can now be configured to ignore certain tables when dumping the schema cache.
278
+ * Add `ActiveRecord.after_all_transactions_commit` callback.
605
279
 
606
- The configuration option can table an array of tables:
280
+ Useful for code that may run either inside or outside a transaction and needs
281
+ to perform work after the state changes have been properly persisted.
607
282
 
608
283
  ```ruby
609
- config.active_record.schema_cache_ignored_tables = ["ignored_table", "another_ignored_table"]
610
- ```
611
-
612
- Or a regex:
613
-
614
- ```ruby
615
- config.active_record.schema_cache_ignored_tables = [/^_/]
616
- ```
617
-
618
- *Eileen M. Uchitelle*
619
-
620
- * Make schema cache methods return consistent results.
621
-
622
- Previously the schema cache methods `primary_keys`, `columns`, `columns_hash`, and `indexes`
623
- would behave differently than one another when a table didn't exist and differently across
624
- database adapters. This change unifies the behavior so each method behaves the same regardless
625
- of adapter.
626
-
627
- The behavior now is:
628
-
629
- `columns`: (unchanged) raises a db error if the table does not exist.
630
- `columns_hash`: (unchanged) raises a db error if the table does not exist.
631
- `primary_keys`: (unchanged) returns `nil` if the table does not exist.
632
- `indexes`: (changed for mysql2) returns `[]` if the table does not exist.
633
-
634
- *Eileen M. Uchitelle*
635
-
636
- * Reestablish connection to previous database after after running `db:schema:load:name`
637
-
638
- After running `db:schema:load:name` the previous connection is restored.
639
-
640
- *Jacopo Beschi*
641
-
642
- * Add database config option `database_tasks`
643
-
644
- If you would like to connect to an external database without any database
645
- management tasks such as schema management, migrations, seeds, etc. you can set
646
- the per database config option `database_tasks: false`
647
-
648
- ```yaml
649
- # config/database.yml
650
-
651
- production:
652
- primary:
653
- database: my_database
654
- adapter: mysql2
655
- animals:
656
- database: my_animals_database
657
- adapter: mysql2
658
- database_tasks: false
284
+ def publish_article(article)
285
+ article.update(published: true)
286
+ ActiveRecord.after_all_transactions_commit do
287
+ PublishNotificationMailer.with(article: article).deliver_later
288
+ end
289
+ end
659
290
  ```
660
291
 
661
- *Weston Ganger*
662
-
663
- * Fix `ActiveRecord::InternalMetadata` to not be broken by `config.active_record.record_timestamps = false`
292
+ In the above example, the block is either executed immediately if called outside
293
+ of a transaction, or called after the open transaction is committed.
664
294
 
665
- Since the model always create the timestamp columns, it has to set them, otherwise it breaks
666
- various DB management tasks.
295
+ If the transaction is rolled back, the block isn't called.
667
296
 
668
- Fixes #42983
297
+ *Jean Boussier*
669
298
 
670
- * Add `ActiveRecord::QueryLogs`.
299
+ * Add the ability to ignore counter cache columns until they are backfilled.
671
300
 
672
- Configurable tags can be automatically added to all SQL queries generated by Active Record.
301
+ Starting to use counter caches on existing large tables can be troublesome, because the column
302
+ values must be backfilled separately of the column addition (to not lock the table for too long)
303
+ and before the use of `:counter_cache` (otherwise methods like `size`/`any?`/etc, which use
304
+ counter caches internally, can produce incorrect results). People usually use database triggers
305
+ or callbacks on child associations while backfilling before introducing a counter cache
306
+ configuration to the association.
673
307
 
674
- ```ruby
675
- # config/application.rb
676
- module MyApp
677
- class Application < Rails::Application
678
- config.active_record.query_log_tags_enabled = true
679
- end
680
- end
681
- ```
682
-
683
- By default the application, controller and action details are added to the query tags:
308
+ Now, to safely backfill the column, while keeping the column updated with child records added/removed, use:
684
309
 
685
310
  ```ruby
686
- class BooksController < ApplicationController
687
- def index
688
- @books = Book.all
689
- end
311
+ class Comment < ApplicationRecord
312
+ belongs_to :post, counter_cache: { active: false }
690
313
  end
691
314
  ```
692
315
 
693
- ```ruby
694
- GET /books
695
- # SELECT * FROM books /*application:MyApp;controller:books;action:index*/
696
- ```
316
+ While the counter cache is not "active", the methods like `size`/`any?`/etc will not use it,
317
+ but get the results directly from the database. After the counter cache column is backfilled, simply
318
+ remove the `{ active: false }` part from the counter cache definition, and it will now be used by the
319
+ mentioned methods.
697
320
 
698
- Custom tags containing static values and Procs can be defined in the application configuration:
699
-
700
- ```ruby
701
- config.active_record.query_log_tags = [
702
- :application,
703
- :controller,
704
- :action,
705
- {
706
- custom_static: "foo",
707
- custom_dynamic: -> { Time.now }
708
- }
709
- ]
710
- ```
711
-
712
- *Keeran Raj Hawoldar*, *Eileen M. Uchitelle*, *Kasper Timm Hansen*
321
+ *fatkodima*
713
322
 
714
- * Added support for multiple databases to `rails db:setup` and `rails db:reset`.
323
+ * Retry known idempotent SELECT queries on connection-related exceptions.
715
324
 
716
- *Ryan Hall*
325
+ SELECT queries we construct by walking the Arel tree and / or with known model attributes
326
+ are idempotent and can safely be retried in the case of a connection error. Previously,
327
+ adapters such as `TrilogyAdapter` would raise `ActiveRecord::ConnectionFailed: Trilogy::EOFError`
328
+ when encountering a connection error mid-request.
717
329
 
718
- * Add `ActiveRecord::Relation#structurally_compatible?`.
330
+ *Adrianna Chang*
719
331
 
720
- Adds a query method by which a user can tell if the relation that they're
721
- about to use for `#or` or `#and` is structurally compatible with the
722
- receiver.
332
+ * Allow association's `foreign_key` to be composite.
723
333
 
724
- *Kevin Newton*
334
+ `query_constraints` option was the only way to configure a composite foreign key by passing an `Array`.
335
+ Now it's possible to pass an Array value as `foreign_key` to achieve the same behavior of an association.
725
336
 
726
- * Add `ActiveRecord::QueryMethods#in_order_of`.
337
+ *Nikita Vasilevsky*
727
338
 
728
- This allows you to specify an explicit order that you'd like records
729
- returned in based on a SQL expression. By default, this will be accomplished
730
- using a case statement, as in:
339
+ * Allow association's `primary_key` to be composite.
731
340
 
732
- ```ruby
733
- Post.in_order_of(:id, [3, 5, 1])
734
- ```
341
+ Association's `primary_key` can be composite when derived from associated model `primary_key` or `query_constraints`.
342
+ Now it's possible to explicitly set it as composite on the association.
735
343
 
736
- will generate the SQL:
344
+ *Nikita Vasilevsky*
737
345
 
738
- ```sql
739
- 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
740
- ```
346
+ * Add `config.active_record.permanent_connection_checkout` setting.
741
347
 
742
- However, because this functionality is built into MySQL in the form of the
743
- `FIELD` function, that connection adapter will generate the following SQL
744
- instead:
348
+ Controls whether `ActiveRecord::Base.connection` raises an error, emits a deprecation warning, or neither.
745
349
 
746
- ```sql
747
- SELECT "posts".* FROM "posts" ORDER BY FIELD("posts"."id", 1, 5, 3) DESC
748
- ```
350
+ `ActiveRecord::Base.connection` checkouts a database connection from the pool and keeps it leased until the end of
351
+ the request or job. This behavior can be undesirable in environments that use many more threads or fibers than there
352
+ is available connections.
749
353
 
750
- *Kevin Newton*
354
+ This configuration can be used to track down and eliminate code that calls `ActiveRecord::Base.connection` and
355
+ migrate it to use `ActiveRecord::Base.with_connection` instead.
751
356
 
752
- * Fix `eager_loading?` when ordering with `Symbol`.
357
+ The default behavior remains unchanged, and there is currently no plans to change the default.
753
358
 
754
- `eager_loading?` is triggered correctly when using `order` with symbols.
359
+ *Jean Boussier*
755
360
 
756
- ```ruby
757
- scope = Post.includes(:comments).order(:"comments.label")
758
- => true
759
- ```
361
+ * Add dirties option to uncached.
760
362
 
761
- *Jacopo Beschi*
363
+ This adds a `dirties` option to `ActiveRecord::Base.uncached` and
364
+ `ActiveRecord::ConnectionAdapters::ConnectionPool#uncached`.
762
365
 
763
- * Two change tracking methods are added for `belongs_to` associations.
366
+ When set to `true` (the default), writes will clear all query caches belonging to the current thread.
367
+ When set to `false`, writes to the affected connection pool will not clear any query cache.
764
368
 
765
- The `association_changed?` method (assuming an association named `:association`) returns true
766
- if a different associated object has been assigned and the foreign key will be updated in the
767
- next save.
369
+ This is needed by Solid Cache so that cache writes do not clear query caches.
768
370
 
769
- The `association_previously_changed?` method returns true if the previous save updated the
770
- association to reference a different associated object.
371
+ *Donal McBreen*
771
372
 
772
- *George Claghorn*
373
+ * Deprecate `ActiveRecord::Base.connection` in favor of `.lease_connection`.
773
374
 
774
- * Add option to disable schema dump per-database.
375
+ The method has been renamed as `lease_connection` to better reflect that the returned
376
+ connection will be held for the duration of the request or job.
775
377
 
776
- Dumping the schema is on by default for all databases in an application. To turn it off for a
777
- specific database, use the `schema_dump` option:
378
+ This deprecation is a soft deprecation, no warnings will be issued and there is no
379
+ current plan to remove the method.
778
380
 
779
- ```yaml
780
- # config/database.yml
381
+ *Jean Boussier*
781
382
 
782
- production:
783
- schema_dump: false
784
- ```
383
+ * Deprecate `ActiveRecord::ConnectionAdapters::ConnectionPool#connection`.
785
384
 
786
- *Luis Vasconcellos*, *Eileen M. Uchitelle*
385
+ The method has been renamed as `lease_connection` to better reflect that the returned
386
+ connection will be held for the duration of the request or job.
787
387
 
788
- * Fix `eager_loading?` when ordering with `Hash` syntax.
388
+ *Jean Boussier*
789
389
 
790
- `eager_loading?` is triggered correctly when using `order` with hash syntax
791
- on an outer table.
390
+ * Expose a generic fixture accessor for fixture names that may conflict with Minitest.
792
391
 
793
392
  ```ruby
794
- Post.includes(:comments).order({ "comments.label": :ASC }).eager_loading?
795
- # => true
393
+ assert_equal "Ruby on Rails", web_sites(:rubyonrails).name
394
+ assert_equal "Ruby on Rails", fixture(:web_sites, :rubyonrails).name
796
395
  ```
797
396
 
798
- *Jacopo Beschi*
799
-
800
- * Move the forcing of clear text encoding to the `ActiveRecord::Encryption::Encryptor`.
397
+ *Jean Boussier*
801
398
 
802
- Fixes #42699.
399
+ * Using `Model.query_constraints` with a single non-primary-key column used to raise as expected, but with an
400
+ incorrect error message.
803
401
 
804
- *J Smith*
402
+ This has been fixed to raise with a more appropriate error message.
805
403
 
806
- * `partial_inserts` is now disabled by default in new apps.
404
+ *Joshua Young*
807
405
 
808
- This will be the default for new apps in Rails 7. To opt in:
406
+ * Fix `has_one` association autosave setting the foreign key attribute when it is unchanged.
809
407
 
810
- ```ruby
811
- config.active_record.partial_inserts = true
812
- ```
408
+ This behavior is also inconsistent with autosaving `belongs_to` and can have unintended side effects like raising
409
+ an `ActiveRecord::ReadonlyAttributeError` when the foreign key attribute is marked as read-only.
813
410
 
814
- If a migration removes the default value of a column, this option
815
- would cause old processes to no longer be able to create new records.
411
+ *Joshua Young*
816
412
 
817
- If you need to remove a column, you should first use `ignored_columns`
818
- to stop using it.
413
+ * Remove deprecated behavior that would rollback a transaction block when exited using `return`, `break` or `throw`.
819
414
 
820
- *Jean Boussier*
415
+ *Rafael Mendonça França*
821
416
 
822
- * Rails can now verify foreign keys after loading fixtures in tests.
417
+ * Deprecate `Rails.application.config.active_record.commit_transaction_on_non_local_return`.
823
418
 
824
- This will be the default for new apps in Rails 7. To opt in:
419
+ *Rafael Mendonça França*
825
420
 
826
- ```ruby
827
- config.active_record.verify_foreign_keys_for_fixtures = true
828
- ```
421
+ * Remove deprecated support to pass `rewhere` to `ActiveRecord::Relation#merge`.
829
422
 
830
- Tests will not run if there is a foreign key constraint violation in your fixture data.
423
+ *Rafael Mendonça França*
831
424
 
832
- The feature is supported by SQLite and PostgreSQL, other adapters can also add support for it.
425
+ * Remove deprecated support to pass `deferrable: true` to `add_foreign_key`.
833
426
 
834
- *Alex Ghiculescu*
427
+ *Rafael Mendonça França*
835
428
 
836
- * Clear cached `has_one` association after setting `belongs_to` association to `nil`.
429
+ * Remove deprecated support to quote `ActiveSupport::Duration`.
837
430
 
838
- After setting a `belongs_to` relation to `nil` and updating an unrelated attribute on the owner,
839
- the owner should still return `nil` on the `has_one` relation.
431
+ *Rafael Mendonça França*
840
432
 
841
- Fixes #42597.
433
+ * Remove deprecated `#quote_bound_value`.
842
434
 
843
- *Michiel de Mare*
435
+ *Rafael Mendonça França*
844
436
 
845
- * OpenSSL constants are now used for Digest computations.
437
+ * Remove deprecated `ActiveRecord::ConnectionAdapters::ConnectionPool#connection_klass`.
846
438
 
847
- *Dirkjan Bussink*
439
+ *Rafael Mendonça França*
848
440
 
849
- * Adds support for `if_not_exists` to `add_foreign_key` and `if_exists` to `remove_foreign_key`.
441
+ * Remove deprecated support to apply `#connection_pool_list`, `#active_connections?`, `#clear_active_connections!`,
442
+ `#clear_reloadable_connections!`, `#clear_all_connections!` and `#flush_idle_connections!` to the connections pools
443
+ for the current role when the `role` argument isn't provided.
850
444
 
851
- Applications can set their migrations to ignore exceptions raised when adding a foreign key
852
- that already exists or when removing a foreign key that does not exist.
445
+ *Rafael Mendonça França*
853
446
 
854
- Example Usage:
447
+ * Remove deprecated `#all_connection_pools`.
855
448
 
856
- ```ruby
857
- class AddAuthorsForeignKeyToArticles < ActiveRecord::Migration[7.0]
858
- def change
859
- add_foreign_key :articles, :authors, if_not_exists: true
860
- end
861
- end
862
- ```
449
+ *Rafael Mendonça França*
863
450
 
864
- ```ruby
865
- class RemoveAuthorsForeignKeyFromArticles < ActiveRecord::Migration[7.0]
866
- def change
867
- remove_foreign_key :articles, :authors, if_exists: true
868
- end
869
- end
870
- ```
451
+ * Remove deprecated `ActiveRecord::ConnectionAdapters::SchemaCache#data_sources`.
871
452
 
872
- *Roberto Miranda*
453
+ *Rafael Mendonça França*
873
454
 
874
- * Prevent polluting ENV during postgresql structure dump/load.
455
+ * Remove deprecated `ActiveRecord::ConnectionAdapters::SchemaCache.load_from`.
875
456
 
876
- Some configuration parameters were provided to pg_dump / psql via
877
- environment variables which persisted beyond the command being run, and may
878
- have caused subsequent commands and connections to fail. Tasks running
879
- across multiple postgresql databases like `rails db:test:prepare` may have
880
- been affected.
457
+ *Rafael Mendonça França*
881
458
 
882
- *Samuel Cochran*
459
+ * Remove deprecated `#all_foreign_keys_valid?` from database adapters.
883
460
 
884
- * Set precision 6 by default for `datetime` columns.
461
+ *Rafael Mendonça França*
885
462
 
886
- By default, datetime columns will have microseconds precision instead of seconds precision.
463
+ * Remove deprecated support to passing coder and class as second argument to `serialize`.
887
464
 
888
- *Roberto Miranda*
465
+ *Rafael Mendonça França*
889
466
 
890
- * Allow preloading of associations with instance dependent scopes.
467
+ * Remove deprecated support to `ActiveRecord::Base#read_attribute(:id)` to return the custom primary key value.
891
468
 
892
- *John Hawthorn*, *John Crepezzi*, *Adam Hess*, *Eileen M. Uchitelle*, *Dinah Shi*
469
+ *Rafael Mendonça França*
893
470
 
894
- * Do not try to rollback transactions that failed due to a `ActiveRecord::TransactionRollbackError`.
471
+ * Remove deprecated `TestFixtures.fixture_path`.
895
472
 
896
- *Jamie McCarthy*
473
+ *Rafael Mendonça França*
897
474
 
898
- * Active Record Encryption will now encode values as UTF-8 when using deterministic
899
- encryption. The encoding is part of the encrypted payload, so different encodings for
900
- different values result in different ciphertexts. This can break unique constraints and
901
- queries.
475
+ * Remove deprecated behavior to support referring to a singular association by its plural name.
902
476
 
903
- The new behavior is configurable via `active_record.encryption.forced_encoding_for_deterministic_encryption`
904
- that is `Encoding::UTF_8` by default. It can be disabled by setting it to `nil`.
477
+ *Rafael Mendonça França*
905
478
 
906
- *Jorge Manrubia*
479
+ * Deprecate `Rails.application.config.active_record.allow_deprecated_singular_associations_name`.
907
480
 
908
- * The MySQL adapter now cast numbers and booleans bind parameters to string for safety reasons.
481
+ *Rafael Mendonça França*
909
482
 
910
- When comparing a string and a number in a query, MySQL converts the string to a number. So for
911
- instance `"foo" = 0`, will implicitly cast `"foo"` to `0` and will evaluate to `TRUE` which can
912
- lead to security vulnerabilities.
483
+ * Remove deprecated support to passing `SchemaMigration` and `InternalMetadata` classes as arguments to
484
+ `ActiveRecord::MigrationContext`.
913
485
 
914
- Active Record already protect against that vulnerability when it knows the type of the column
915
- being compared, however until now it was still vulnerable when using bind parameters:
486
+ *Rafael Mendonça França*
916
487
 
917
- ```ruby
918
- User.where("login_token = ?", 0).first
919
- ```
488
+ * Remove deprecated `ActiveRecord::Migration.check_pending!` method.
920
489
 
921
- Would perform:
490
+ *Rafael Mendonça França*
922
491
 
923
- ```sql
924
- SELECT * FROM `users` WHERE `login_token` = 0 LIMIT 1;
925
- ```
492
+ * Remove deprecated `ActiveRecord::LogSubscriber.runtime` method.
926
493
 
927
- Now it will perform:
494
+ *Rafael Mendonça França*
928
495
 
929
- ```sql
930
- SELECT * FROM `users` WHERE `login_token` = '0' LIMIT 1;
931
- ```
496
+ * Remove deprecated `ActiveRecord::LogSubscriber.runtime=` method.
932
497
 
933
- *Jean Boussier*
498
+ *Rafael Mendonça França*
934
499
 
935
- * Fixture configurations (`_fixture`) are now strictly validated.
500
+ * Remove deprecated `ActiveRecord::LogSubscriber.reset_runtime` method.
936
501
 
937
- If an error will be raised if that entry contains unknown keys while previously it
938
- would silently have no effects.
502
+ *Rafael Mendonça França*
939
503
 
940
- *Jean Boussier*
504
+ * Remove deprecated support to define `explain` in the connection adapter with 2 arguments.
941
505
 
942
- * Add `ActiveRecord::Base.update!` that works like `ActiveRecord::Base.update` but raises exceptions.
506
+ *Rafael Mendonça França*
943
507
 
944
- This allows for the same behavior as the instance method `#update!` at a class level.
508
+ * Remove deprecated `ActiveRecord::ActiveJobRequiredError`.
945
509
 
946
- ```ruby
947
- Person.update!(:all, state: "confirmed")
948
- ```
510
+ *Rafael Mendonça França*
949
511
 
950
- *Dorian Marié*
512
+ * Remove deprecated `ActiveRecord::Base.clear_active_connections!`.
951
513
 
952
- * Add `ActiveRecord::Base#attributes_for_database`.
514
+ *Rafael Mendonça França*
953
515
 
954
- Returns attributes with values for assignment to the database.
516
+ * Remove deprecated `ActiveRecord::Base.clear_reloadable_connections!`.
955
517
 
956
- *Chris Salzberg*
518
+ *Rafael Mendonça França*
957
519
 
958
- * Use an empty query to check if the PostgreSQL connection is still active.
520
+ * Remove deprecated `ActiveRecord::Base.clear_all_connections!`.
959
521
 
960
- An empty query is faster than `SELECT 1`.
522
+ *Rafael Mendonça França*
961
523
 
962
- *Heinrich Lee Yu*
524
+ * Remove deprecated `ActiveRecord::Base.flush_idle_connections!`.
963
525
 
964
- * Add `ActiveRecord::Base#previously_persisted?`.
526
+ *Rafael Mendonça França*
965
527
 
966
- Returns `true` if the object has been previously persisted but now it has been deleted.
528
+ * Remove deprecated `name` argument from `ActiveRecord::Base.remove_connection`.
967
529
 
968
- * Deprecate `partial_writes` in favor of `partial_inserts` and `partial_updates`.
530
+ *Rafael Mendonça França*
969
531
 
970
- This allows to have a different behavior on update and create.
532
+ * Remove deprecated support to call `alias_attribute` with non-existent attribute names.
971
533
 
972
- *Jean Boussier*
534
+ *Rafael Mendonça França*
973
535
 
974
- * Fix compatibility with `psych >= 4`.
536
+ * Remove deprecated `Rails.application.config.active_record.suppress_multiple_database_warning`.
975
537
 
976
- Starting in Psych 4.0.0 `YAML.load` behaves like `YAML.safe_load`. To preserve compatibility,
977
- Active Record's schema cache loader and `YAMLColumn` now uses `YAML.unsafe_load` if available.
538
+ *Rafael Mendonça França*
978
539
 
979
- *Jean Boussier*
540
+ * Add `ActiveRecord::Encryption::MessagePackMessageSerializer`.
980
541
 
981
- * `ActiveRecord::Base.logger` is now a `class_attribute`.
542
+ Serialize data to the MessagePack format, for efficient storage in binary columns.
982
543
 
983
- This means it can no longer be accessed directly through `@@logger`, and that setting `logger =`
984
- on a subclass won't change the parent's logger.
544
+ The binary encoding requires around 30% less space than the base64 encoding
545
+ used by the default serializer.
985
546
 
986
- *Jean Boussier*
547
+ *Donal McBreen*
987
548
 
988
- * Add `.asc.nulls_first` for all databases. Unfortunately MySQL still doesn't like `nulls_last`.
549
+ * Add support for encrypting binary columns.
989
550
 
990
- *Keenan Brock*
551
+ Ensure encryption and decryption pass `Type::Binary::Data` around for binary data.
991
552
 
992
- * Improve performance of `one?` and `many?` by limiting the generated count query to 2 results.
553
+ Previously encrypting binary columns with the `ActiveRecord::Encryption::MessageSerializer`
554
+ incidentally worked for MySQL and SQLite, but not PostgreSQL.
993
555
 
994
- *Gonzalo Riestra*
556
+ *Donal McBreen*
995
557
 
996
- * Don't check type when using `if_not_exists` on `add_column`.
558
+ * Deprecated `ENV["SCHEMA_CACHE"]` in favor of `schema_cache_path` in the database configuration.
997
559
 
998
- Previously, if a migration called `add_column` with the `if_not_exists` option set to true
999
- the `column_exists?` check would look for a column with the same name and type as the migration.
560
+ *Rafael Mendonça França*
1000
561
 
1001
- Recently it was discovered that the type passed to the migration is not always the same type
1002
- as the column after migration. For example a column set to `:mediumblob` in the migration will
1003
- be casted to `binary` when calling `column.type`. Since there is no straightforward way to cast
1004
- the type to the database type without running the migration, we opted to drop the type check from
1005
- `add_column`. This means that migrations adding a duplicate column with a different type will no
1006
- longer raise an error.
562
+ * Add `ActiveRecord::Base.with_connection` as a shortcut for leasing a connection for a short duration.
1007
563
 
1008
- *Eileen M. Uchitelle*
564
+ The leased connection is yielded, and for the duration of the block, any call to `ActiveRecord::Base.connection`
565
+ will yield that same connection.
1009
566
 
1010
- * Log a warning message when running SQLite in production.
567
+ This is useful to perform a few database operations without causing a connection to be leased for the
568
+ entire duration of the request or job.
1011
569
 
1012
- Using SQLite in production ENV is generally discouraged. SQLite is also the default adapter
1013
- in a new Rails application.
1014
- For the above reasons log a warning message when running SQLite in production.
570
+ *Jean Boussier*
1015
571
 
1016
- The warning can be disabled by setting `config.active_record.sqlite3_production_warning=false`.
572
+ * Deprecate `config.active_record.warn_on_records_fetched_greater_than` now that `sql.active_record`
573
+ notification includes `:row_count` field.
1017
574
 
1018
- *Jacopo Beschi*
575
+ *Jason Nochlin*
1019
576
 
1020
- * Add option to disable joins for `has_one` associations.
577
+ * The fix ensures that the association is joined using the appropriate join type
578
+ (either inner join or left outer join) based on the existing joins in the scope.
1021
579
 
1022
- In a multiple database application, associations can't join across
1023
- databases. When set, this option instructs Rails to generate 2 or
1024
- more queries rather than generating joins for `has_one` associations.
580
+ This prevents unintentional overrides of existing join types and ensures consistency in the generated SQL queries.
1025
581
 
1026
- Set the option on a has one through association:
582
+ Example:
1027
583
 
1028
- ```ruby
1029
- class Person
1030
- has_one :dog
1031
- has_one :veterinarian, through: :dog, disable_joins: true
1032
- end
1033
- ```
1034
584
 
1035
- Then instead of generating join SQL, two queries are used for `@person.veterinarian`:
1036
585
 
586
+ ```ruby
587
+ # `associated` will use `LEFT JOIN` instead of using `JOIN`
588
+ Post.left_joins(:author).where.associated(:author)
1037
589
  ```
1038
- SELECT "dogs"."id" FROM "dogs" WHERE "dogs"."person_id" = ? [["person_id", 1]]
1039
- SELECT "veterinarians".* FROM "veterinarians" WHERE "veterinarians"."dog_id" = ? [["dog_id", 1]]
1040
- ```
1041
-
1042
- *Sarah Vessels*, *Eileen M. Uchitelle*
1043
-
1044
- * `Arel::Visitors::Dot` now renders a complete set of properties when visiting
1045
- `Arel::Nodes::SelectCore`, `SelectStatement`, `InsertStatement`, `UpdateStatement`, and
1046
- `DeleteStatement`, which fixes #42026. Previously, some properties were omitted.
1047
590
 
1048
- *Mike Dalessio*
591
+ *Saleh Alhaddad*
1049
592
 
1050
- * `Arel::Visitors::Dot` now supports `Arel::Nodes::Bin`, `Case`, `CurrentRow`, `Distinct`,
1051
- `DistinctOn`, `Else`, `Except`, `InfixOperation`, `Intersect`, `Lock`, `NotRegexp`, `Quoted`,
1052
- `Regexp`, `UnaryOperation`, `Union`, `UnionAll`, `When`, and `With`. Previously, these node
1053
- types caused an exception to be raised by `Arel::Visitors::Dot#accept`.
593
+ * Fix an issue where `ActiveRecord::Encryption` configurations are not ready before the loading
594
+ of Active Record models, when an application is eager loaded. As a result, encrypted attributes
595
+ could be misconfigured in some cases.
1054
596
 
1055
- *Mike Dalessio*
597
+ *Maxime Réty*
1056
598
 
1057
- * Optimize `remove_columns` to use a single SQL statement.
599
+ * Deprecate defining an `enum` with keyword arguments.
1058
600
 
1059
601
  ```ruby
1060
- remove_columns :my_table, :col_one, :col_two
1061
- ```
1062
-
1063
- Now results in the following SQL:
602
+ class Function > ApplicationRecord
603
+ # BAD
604
+ enum color: [:red, :blue],
605
+ type: [:instance, :class]
1064
606
 
1065
- ```sql
1066
- ALTER TABLE "my_table" DROP COLUMN "col_one", DROP COLUMN "col_two"
607
+ # GOOD
608
+ enum :color, [:red, :blue]
609
+ enum :type, [:instance, :class]
610
+ end
1067
611
  ```
1068
612
 
1069
- *Jon Dufresne*
613
+ *Hartley McGuire*
1070
614
 
1071
- * Ensure `has_one` autosave association callbacks get called once.
615
+ * Add `config.active_record.validate_migration_timestamps` option for validating migration timestamps.
1072
616
 
1073
- Change the `has_one` autosave callback to be non cyclic as well.
1074
- By doing this the autosave callback are made more consistent for
1075
- all 3 cases: `has_many`, `has_one`, and `belongs_to`.
617
+ When set, validates that the timestamp prefix for a migration is no more than a day ahead of
618
+ the timestamp associated with the current time. This is designed to prevent migrations prefixes
619
+ from being hand-edited to future timestamps, which impacts migration generation and other
620
+ migration commands.
1076
621
 
1077
- *Petrik de Heus*
622
+ *Adrianna Chang*
1078
623
 
1079
- * Add option to disable joins for associations.
624
+ * Properly synchronize `Mysql2Adapter#active?` and `TrilogyAdapter#active?`.
1080
625
 
1081
- In a multiple database application, associations can't join across
1082
- databases. When set, this option instructs Rails to generate 2 or
1083
- more queries rather than generating joins for associations.
626
+ As well as `disconnect!` and `verify!`.
1084
627
 
1085
- Set the option on a has many through association:
628
+ This generally isn't a big problem as connections must not be shared between
629
+ threads, but is required when running transactional tests or system tests
630
+ and could lead to a SEGV.
1086
631
 
1087
- ```ruby
1088
- class Dog
1089
- has_many :treats, through: :humans, disable_joins: true
1090
- has_many :humans
1091
- end
1092
- ```
632
+ *Jean Boussier*
1093
633
 
1094
- Then instead of generating join SQL, two queries are used for `@dog.treats`:
634
+ * Support `:source_location` tag option for query log tags.
1095
635
 
636
+ ```ruby
637
+ config.active_record.query_log_tags << :source_location
1096
638
  ```
1097
- SELECT "humans"."id" FROM "humans" WHERE "humans"."dog_id" = ? [["dog_id", 1]]
1098
- SELECT "treats".* FROM "treats" WHERE "treats"."human_id" IN (?, ?, ?) [["human_id", 1], ["human_id", 2], ["human_id", 3]]
1099
- ```
1100
-
1101
- *Eileen M. Uchitelle*, *Aaron Patterson*, *Lee Quarella*
1102
-
1103
- * Add setting for enumerating column names in SELECT statements.
1104
639
 
1105
- Adding a column to a PostgreSQL database, for example, while the application is running can
1106
- change the result of wildcard `SELECT *` queries, which invalidates the result
1107
- of cached prepared statements and raises a `PreparedStatementCacheExpired` error.
640
+ Calculating the caller location is a costly operation and should be used primarily in development
641
+ (note, there is also a `config.active_record.verbose_query_logs` that serves the same purpose)
642
+ or occasionally on production for debugging purposes.
1108
643
 
1109
- When enabled, Active Record will avoid wildcards and always include column names
1110
- in `SELECT` queries, which will return consistent results and avoid prepared
1111
- statement errors.
644
+ *fatkodima*
1112
645
 
1113
- Before:
646
+ * Add an option to `ActiveRecord::Encryption::Encryptor` to disable compression.
1114
647
 
1115
- ```ruby
1116
- Book.limit(5)
1117
- # SELECT * FROM books LIMIT 5
1118
- ```
1119
-
1120
- After:
648
+ Allow compression to be disabled by setting `compress: false`
1121
649
 
1122
650
  ```ruby
1123
- # config/application.rb
1124
- module MyApp
1125
- class Application < Rails::Application
1126
- config.active_record.enumerate_columns_in_select_statements = true
651
+ class User
652
+ encrypts :name, encryptor: ActiveRecord::Encryption::Encryptor.new(compress: false)
1127
653
  end
1128
- end
1129
-
1130
- # or, configure per-model
1131
- class Book < ApplicationRecord
1132
- self.enumerate_columns_in_select_statements = true
1133
- end
1134
654
  ```
1135
655
 
1136
- ```ruby
1137
- Book.limit(5)
1138
- # SELECT id, author_id, name, format, status, language, etc FROM books LIMIT 5
1139
- ```
656
+ *Donal McBreen*
1140
657
 
1141
- *Matt Duszynski*
658
+ * Deprecate passing strings to `ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename`.
1142
659
 
1143
- * Allow passing SQL as `on_duplicate` value to `#upsert_all` to make it possible to use raw SQL to update columns on conflict:
660
+ A `ActiveRecord::DatabaseConfigurations::DatabaseConfig` object should be passed instead.
1144
661
 
1145
- ```ruby
1146
- Book.upsert_all(
1147
- [{ id: 1, status: 1 }, { id: 2, status: 1 }],
1148
- on_duplicate: Arel.sql("status = GREATEST(books.status, EXCLUDED.status)")
1149
- )
1150
- ```
662
+ *Rafael Mendonça França*
1151
663
 
1152
- *Vladimir Dementyev*
664
+ * Add `row_count` field to `sql.active_record` notification.
1153
665
 
1154
- * Allow passing SQL as `returning` statement to `#upsert_all`:
666
+ This field returns the amount of rows returned by the query that emitted the notification.
1155
667
 
1156
- ```ruby
1157
- Article.insert_all(
1158
- [
1159
- { title: "Article 1", slug: "article-1", published: false },
1160
- { title: "Article 2", slug: "article-2", published: false }
1161
- ],
1162
- returning: Arel.sql("id, (xmax = '0') as inserted, name as new_name")
1163
- )
1164
- ```
668
+ This metric is useful in cases where one wants to detect queries with big result sets.
1165
669
 
1166
- *Vladimir Dementyev*
670
+ *Marvin Bitterlich*
1167
671
 
1168
- * Deprecate `legacy_connection_handling`.
672
+ * Consistently raise an `ArgumentError` when passing an invalid argument to a nested attributes association writer.
1169
673
 
1170
- *Eileen M. Uchitelle*
674
+ Previously, this would only raise on collection associations and produce a generic error on singular associations.
1171
675
 
1172
- * Add attribute encryption support.
676
+ Now, it will raise on both collection and singular associations.
1173
677
 
1174
- Encrypted attributes are declared at the model level. These
1175
- are regular Active Record attributes backed by a column with
1176
- the same name. The system will transparently encrypt these
1177
- attributes before saving them into the database and will
1178
- decrypt them when retrieving their values.
678
+ *Joshua Young*
1179
679
 
680
+ * Fix single quote escapes on default generated MySQL columns.
1180
681
 
1181
- ```ruby
1182
- class Person < ApplicationRecord
1183
- encrypts :name
1184
- encrypts :email_address, deterministic: true
1185
- end
1186
- ```
682
+ MySQL 5.7.5+ supports generated columns, which can be used to create a column that is computed from an expression.
1187
683
 
1188
- You can learn more in the [Active Record Encryption
1189
- guide](https://edgeguides.rubyonrails.org/active_record_encryption.html).
684
+ Previously, the schema dump would output a string with double escapes for generated columns with single quotes in the default expression.
1190
685
 
1191
- *Jorge Manrubia*
686
+ This would result in issues when importing the schema on a fresh instance of a MySQL database.
1192
687
 
1193
- * Changed Arel predications `contains` and `overlaps` to use
1194
- `quoted_node` so that PostgreSQL arrays are quoted properly.
688
+ Now, the string will not be escaped and will be valid Ruby upon importing of the schema.
1195
689
 
1196
- *Bradley Priest*
690
+ *Yash Kapadia*
1197
691
 
1198
- * Add mode argument to record level `strict_loading!`.
692
+ * Fix Migrations with versions older than 7.1 validating options given to
693
+ `add_reference` and `t.references`.
1199
694
 
1200
- This argument can be used when enabling strict loading for a single record
1201
- to specify that we only want to raise on n plus one queries.
695
+ *Hartley McGuire*
1202
696
 
1203
- ```ruby
1204
- developer.strict_loading!(mode: :n_plus_one_only)
697
+ * Add `<role>_types` class method to `ActiveRecord::DelegatedType` so that the delegated types can be introspected.
1205
698
 
1206
- developer.projects.to_a # Does not raise
1207
- developer.projects.first.client # Raises StrictLoadingViolationError
1208
- ```
699
+ *JP Rosevear*
1209
700
 
1210
- Previously, enabling strict loading would cause any lazily loaded
1211
- association to raise an error. Using `n_plus_one_only` mode allows us to
1212
- lazily load belongs_to, has_many, and other associations that are fetched
1213
- through a single query.
701
+ * Make `schema_dump`, `query_cache`, `replica` and `database_tasks` configurable via `DATABASE_URL`.
1214
702
 
1215
- *Dinah Shi*
703
+ This wouldn't always work previously because boolean values would be interpreted as strings.
1216
704
 
1217
- * Fix Float::INFINITY assignment to datetime column with postgresql adapter.
705
+ e.g. `DATABASE_URL=postgres://localhost/foo?schema_dump=false` now properly disable dumping the schema
706
+ cache.
1218
707
 
1219
- Before:
708
+ *Mike Coutermarsh*, *Jean Boussier*
1220
709
 
1221
- ```ruby
1222
- # With this config
1223
- ActiveRecord::Base.time_zone_aware_attributes = true
710
+ * Introduce `ActiveRecord::Transactions::ClassMethods#set_callback`.
1224
711
 
1225
- # and the following schema:
1226
- create_table "postgresql_infinities" do |t|
1227
- t.datetime "datetime"
1228
- end
712
+ It is identical to `ActiveSupport::Callbacks::ClassMethods#set_callback`
713
+ but with support for `after_commit` and `after_rollback` callback options.
1229
714
 
1230
- # This test fails
1231
- record = PostgresqlInfinity.create!(datetime: Float::INFINITY)
1232
- assert_equal Float::INFINITY, record.datetime # record.datetime gets nil
1233
- ```
715
+ *Joshua Young*
1234
716
 
1235
- After this commit, `record.datetime` gets `Float::INFINITY` as expected.
717
+ * Make `ActiveRecord::Encryption::Encryptor` agnostic of the serialization format used for encrypted data.
1236
718
 
1237
- *Shunichi Ikegami*
719
+ Previously, the encryptor instance only allowed an encrypted value serialized as a `String` to be passed to the message serializer.
1238
720
 
1239
- * Type cast enum values by the original attribute type.
721
+ Now, the encryptor lets the configured `message_serializer` decide which types of serialized encrypted values are supported. A custom serialiser is therefore allowed to serialize `ActiveRecord::Encryption::Message` objects using a type other than `String`.
1240
722
 
1241
- The notable thing about this change is that unknown labels will no longer match 0 on MySQL.
723
+ The default `ActiveRecord::Encryption::MessageSerializer` already ensures that only `String` objects are passed for deserialization.
1242
724
 
1243
- ```ruby
1244
- class Book < ActiveRecord::Base
1245
- enum :status, { proposed: 0, written: 1, published: 2 }
1246
- end
1247
- ```
725
+ *Maxime Réty*
1248
726
 
1249
- Before:
727
+ * Fix `encrypted_attribute?` to take into account context properties passed to `encrypts`.
1250
728
 
1251
- ```ruby
1252
- # SELECT `books`.* FROM `books` WHERE `books`.`status` = 'prohibited' LIMIT 1
1253
- Book.find_by(status: :prohibited)
1254
- # => #<Book id: 1, status: "proposed", ...> (for mysql2 adapter)
1255
- # => ActiveRecord::StatementInvalid: PG::InvalidTextRepresentation: ERROR: invalid input syntax for type integer: "prohibited" (for postgresql adapter)
1256
- # => nil (for sqlite3 adapter)
1257
- ```
729
+ *Maxime Réty*
1258
730
 
1259
- After:
731
+ * The object returned by `explain` now responds to `pluck`, `first`,
732
+ `last`, `average`, `count`, `maximum`, `minimum`, and `sum`. Those
733
+ new methods run `EXPLAIN` on the corresponding queries:
1260
734
 
1261
735
  ```ruby
1262
- # SELECT `books`.* FROM `books` WHERE `books`.`status` IS NULL LIMIT 1
1263
- Book.find_by(status: :prohibited)
1264
- # => nil (for all adapters)
1265
- ```
1266
-
1267
- *Ryuta Kamizono*
736
+ User.all.explain.count
737
+ # EXPLAIN SELECT COUNT(*) FROM `users`
738
+ # ...
1268
739
 
1269
- * Fixtures for `has_many :through` associations now load timestamps on join tables.
1270
-
1271
- Given this fixture:
1272
-
1273
- ```yml
1274
- ### monkeys.yml
1275
- george:
1276
- name: George the Monkey
1277
- fruits: apple
1278
-
1279
- ### fruits.yml
1280
- apple:
1281
- name: apple
740
+ User.all.explain.maximum(:id)
741
+ # EXPLAIN SELECT MAX(`users`.`id`) FROM `users`
742
+ # ...
1282
743
  ```
1283
744
 
1284
- If the join table (`fruit_monkeys`) contains `created_at` or `updated_at` columns,
1285
- these will now be populated when loading the fixture. Previously, fixture loading
1286
- would crash if these columns were required, and leave them as null otherwise.
1287
-
1288
- *Alex Ghiculescu*
1289
-
1290
- * Allow applications to configure the thread pool for async queries.
1291
-
1292
- Some applications may want one thread pool per database whereas others want to use
1293
- a single global thread pool for all queries. By default, Rails will set `async_query_executor`
1294
- to `nil` which will not initialize any executor. If `load_async` is called and no executor
1295
- has been configured, the query will be executed in the foreground.
745
+ *Petrik de Heus*
1296
746
 
1297
- To create one thread pool for all database connections to use applications can set
1298
- `config.active_record.async_query_executor` to `:global_thread_pool` and optionally define
1299
- `config.active_record.global_executor_concurrency`. This defaults to 4. For applications that want
1300
- to have a thread pool for each database connection, `config.active_record.async_query_executor` can
1301
- be set to `:multi_thread_pool`. The configuration for each thread pool is set in the database
1302
- configuration.
747
+ * Fixes an issue where `validates_associated` `:on` option wasn't respected
748
+ when validating associated records.
1303
749
 
1304
- *Eileen M. Uchitelle*
750
+ *Austen Madden*, *Alex Ghiculescu*, *Rafał Brize*
1305
751
 
1306
- * Allow new syntax for `enum` to avoid leading `_` from reserved options.
752
+ * Allow overriding SQLite defaults from `database.yml`.
1307
753
 
1308
- Before:
754
+ Any PRAGMA configuration set under the `pragmas` key in the configuration
755
+ file takes precedence over Rails' defaults, and additional PRAGMAs can be
756
+ set as well.
1309
757
 
1310
- ```ruby
1311
- class Book < ActiveRecord::Base
1312
- enum status: [ :proposed, :written ], _prefix: true, _scopes: false
1313
- enum cover: [ :hard, :soft ], _suffix: true, _default: :hard
1314
- end
758
+ ```yaml
759
+ database: storage/development.sqlite3
760
+ timeout: 5000
761
+ pragmas:
762
+ journal_mode: off
763
+ temp_store: memory
1315
764
  ```
1316
765
 
1317
- After:
1318
-
1319
- ```ruby
1320
- class Book < ActiveRecord::Base
1321
- enum :status, [ :proposed, :written ], prefix: true, scopes: false
1322
- enum :cover, [ :hard, :soft ], suffix: true, default: :hard
1323
- end
1324
- ```
766
+ *Stephen Margheim*
1325
767
 
1326
- *Ryuta Kamizono*
768
+ * Remove warning message when running SQLite in production, but leave it unconfigured.
1327
769
 
1328
- * Add `ActiveRecord::Relation#load_async`.
770
+ There are valid use cases for running SQLite in production. However, it must be done
771
+ with care, so instead of a warning most users won't see anyway, it's preferable to
772
+ leave the configuration commented out to force them to think about having the database
773
+ on a persistent volume etc.
1329
774
 
1330
- This method schedules the query to be performed asynchronously from a thread pool.
775
+ *Jacopo Beschi*, *Jean Boussier*
1331
776
 
1332
- If the result is accessed before a background thread had the opportunity to perform
1333
- the query, it will be performed in the foreground.
777
+ * Add support for generated columns to the SQLite3 adapter.
1334
778
 
1335
- This is useful for queries that can be performed long enough before their result will be
1336
- needed, or for controllers which need to perform several independent queries.
779
+ Generated columns (both stored and dynamic) are supported since version 3.31.0 of SQLite.
780
+ This adds support for those to the SQLite3 adapter.
1337
781
 
1338
782
  ```ruby
1339
- def index
1340
- @categories = Category.some_complex_scope.load_async
1341
- @posts = Post.some_complex_scope.load_async
783
+ create_table :users do |t|
784
+ t.string :name
785
+ t.virtual :name_upper, type: :string, as: 'UPPER(name)'
786
+ t.virtual :name_lower, type: :string, as: 'LOWER(name)', stored: true
1342
787
  end
1343
788
  ```
1344
789
 
1345
- Active Record logs will also include timing info for the duration of how long
1346
- the main thread had to wait to access the result. This timing is useful to know
1347
- whether or not it's worth to load the query asynchronously.
790
+ *Stephen Margheim*
1348
791
 
1349
- ```
1350
- DEBUG -- : Category Load (62.1ms) SELECT * FROM `categories` LIMIT 50
1351
- DEBUG -- : ASYNC Post Load (64ms) (db time 126.1ms) SELECT * FROM `posts` LIMIT 100
1352
- ```
792
+ * TrilogyAdapter: ignore `host` if `socket` parameter is set.
1353
793
 
1354
- The duration in the first set of parens is how long the main thread was blocked
1355
- waiting for the results, and the second set of parens with "db time" is how long
1356
- the entire query took to execute.
1357
-
1358
- *Jean Boussier*
794
+ This allows to configure a connection on a UNIX socket via `DATABASE_URL`:
1359
795
 
1360
- * Implemented `ActiveRecord::Relation#excluding` method.
1361
-
1362
- This method excludes the specified record (or collection of records) from
1363
- the resulting relation:
1364
-
1365
- ```ruby
1366
- Post.excluding(post)
1367
- Post.excluding(post_one, post_two)
1368
796
  ```
1369
-
1370
- Also works on associations:
1371
-
1372
- ```ruby
1373
- post.comments.excluding(comment)
1374
- post.comments.excluding(comment_one, comment_two)
797
+ DATABASE_URL=trilogy://does-not-matter/my_db_production?socket=/var/run/mysql.sock
1375
798
  ```
1376
799
 
1377
- This is short-hand for `Post.where.not(id: post.id)` (for a single record)
1378
- and `Post.where.not(id: [post_one.id, post_two.id])` (for a collection).
1379
-
1380
- *Glen Crawford*
1381
-
1382
- * Skip optimised #exist? query when #include? is called on a relation
1383
- with a having clause.
800
+ *Jean Boussier*
1384
801
 
1385
- Relations that have aliased select values AND a having clause that
1386
- references an aliased select value would generate an error when
1387
- #include? was called, due to an optimisation that would generate
1388
- call #exists? on the relation instead, which effectively alters
1389
- the select values of the query (and thus removes the aliased select
1390
- values), but leaves the having clause intact. Because the having
1391
- clause is then referencing an aliased column that is no longer
1392
- present in the simplified query, an ActiveRecord::InvalidStatement
1393
- error was raised.
802
+ * Make `assert_queries_count`, `assert_no_queries`, `assert_queries_match`, and
803
+ `assert_no_queries_match` assertions public.
1394
804
 
1395
- A sample query affected by this problem:
805
+ To assert the expected number of queries are made, Rails internally uses `assert_queries_count` and
806
+ `assert_no_queries`. To assert that specific SQL queries are made, `assert_queries_match` and
807
+ `assert_no_queries_match` are used. These assertions can now be used in applications as well.
1396
808
 
1397
809
  ```ruby
1398
- Author.select('COUNT(*) as total_posts', 'authors.*')
1399
- .joins(:posts)
1400
- .group(:id)
1401
- .having('total_posts > 2')
1402
- .include?(Author.first)
1403
- ```
1404
-
1405
- This change adds an addition check to the condition that skips the
1406
- simplified #exists? query, which simply checks for the presence of
1407
- a having clause.
1408
-
1409
- Fixes #41417.
1410
-
1411
- *Michael Smart*
1412
-
1413
- * Increment postgres prepared statement counter before making a prepared statement, so if the statement is aborted
1414
- without Rails knowledge (e.g., if app gets killed during long-running query or due to Rack::Timeout), app won't end
1415
- up in perpetual crash state for being inconsistent with PostgreSQL.
1416
-
1417
- *wbharding*, *Martin Tepper*
1418
-
1419
- * Add ability to apply `scoping` to `all_queries`.
1420
-
1421
- Some applications may want to use the `scoping` method but previously it only
1422
- worked on certain types of queries. This change allows the `scoping` method to apply
1423
- to all queries for a model in a block.
810
+ class ArticleTest < ActiveSupport::TestCase
811
+ test "queries are made" do
812
+ assert_queries_count(1) { Article.first }
813
+ end
1424
814
 
1425
- ```ruby
1426
- Post.where(blog_id: post.blog_id).scoping(all_queries: true) do
1427
- post.update(title: "a post title") # adds `posts.blog_id = 1` to the query
815
+ test "creates a foreign key" do
816
+ assert_queries_match(/ADD FOREIGN KEY/i, include_schema: true) do
817
+ @connection.add_foreign_key(:comments, :posts)
818
+ end
819
+ end
1428
820
  end
1429
821
  ```
1430
822
 
1431
- *Eileen M. Uchitelle*
1432
-
1433
- * `ActiveRecord::Calculations.calculate` called with `:average`
1434
- (aliased as `ActiveRecord::Calculations.average`) will now use column-based
1435
- type casting. This means that floating-point number columns will now be
1436
- aggregated as `Float` and decimal columns will be aggregated as `BigDecimal`.
823
+ *Petrik de Heus*, *fatkodima*
1437
824
 
1438
- Integers are handled as a special case returning `BigDecimal` always
1439
- (this was the case before already).
825
+ * Fix `has_secure_token` calls the setter method on initialize.
1440
826
 
1441
- ```ruby
1442
- # With the following schema:
1443
- create_table "measurements" do |t|
1444
- t.float "temperature"
1445
- end
827
+ *Abeid Ahmed*
1446
828
 
1447
- # Before:
1448
- Measurement.average(:temperature).class
1449
- # => BigDecimal
829
+ * When using a `DATABASE_URL`, allow for a configuration to map the protocol in the URL to a specific database
830
+ adapter. This allows decoupling the adapter the application chooses to use from the database connection details
831
+ set in the deployment environment.
1450
832
 
1451
- # After:
1452
- Measurement.average(:temperature).class
1453
- # => Float
833
+ ```ruby
834
+ # ENV['DATABASE_URL'] = "mysql://localhost/example_database"
835
+ config.active_record.protocol_adapters.mysql = "trilogy"
836
+ # will connect to MySQL using the trilogy adapter
1454
837
  ```
1455
838
 
1456
- Before this change, Rails just called `to_d` on average aggregates from the
1457
- database adapter. This is not the case anymore. If you relied on that kind
1458
- of magic, you now need to register your own `ActiveRecord::Type`
1459
- (see `ActiveRecord::Attributes::ClassMethods` for documentation).
1460
-
1461
- *Josua Schmid*
1462
-
1463
- * PostgreSQL: introduce `ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.datetime_type`.
1464
-
1465
- This setting controls what native type Active Record should use when you call `datetime` in
1466
- a migration or schema. It takes a symbol which must correspond to one of the configured
1467
- `NATIVE_DATABASE_TYPES`. The default is `:timestamp`, meaning `t.datetime` in a migration
1468
- will create a "timestamp without time zone" column. To use "timestamp with time zone",
1469
- change this to `:timestamptz` in an initializer.
1470
-
1471
- You should run `bin/rails db:migrate` to rebuild your schema.rb if you change this.
839
+ *Jean Boussier*, *Kevin McPhillips*
1472
840
 
1473
- *Alex Ghiculescu*
841
+ * In cases where MySQL returns `warning_count` greater than zero, but returns no warnings when
842
+ the `SHOW WARNINGS` query is executed, `ActiveRecord.db_warnings_action` proc will still be
843
+ called with a generic warning message rather than silently ignoring the warning(s).
1474
844
 
1475
- * PostgreSQL: handle `timestamp with time zone` columns correctly in `schema.rb`.
845
+ *Kevin McPhillips*
1476
846
 
1477
- Previously they dumped as `t.datetime :column_name`, now they dump as `t.timestamptz :column_name`,
1478
- and are created as `timestamptz` columns when the schema is loaded.
847
+ * `DatabaseConfigurations#configs_for` accepts a symbol in the `name` parameter.
1479
848
 
1480
- *Alex Ghiculescu*
849
+ *Andrew Novoselac*
1481
850
 
1482
- * Removing trailing whitespace when matching columns in
1483
- `ActiveRecord::Sanitization.disallow_raw_sql!`.
851
+ * Fix `where(field: values)` queries when `field` is a serialized attribute
852
+ (for example, when `field` uses `ActiveRecord::Base.serialize` or is a JSON
853
+ column).
1484
854
 
1485
- *Gannon McGibbon*, *Adrian Hirt*
855
+ *João Alves*
1486
856
 
1487
- * Expose a way for applications to set a `primary_abstract_class`.
857
+ * Make the output of `ActiveRecord::Core#inspect` configurable.
1488
858
 
1489
- Multiple database applications that use a primary abstract class that is not
1490
- named `ApplicationRecord` can now set a specific class to be the `primary_abstract_class`.
859
+ By default, calling `inspect` on a record will yield a formatted string including just the `id`.
1491
860
 
1492
861
  ```ruby
1493
- class PrimaryApplicationRecord
1494
- self.primary_abstract_class
1495
- end
862
+ Post.first.inspect #=> "#<Post id: 1>"
1496
863
  ```
1497
864
 
1498
- When an application boots it automatically connects to the primary or first database in the
1499
- database configuration file. In a multiple database application that then call `connects_to`
1500
- needs to know that the default connection is the same as the `ApplicationRecord` connection.
1501
- However, some applications have a differently named `ApplicationRecord`. This prevents Active
1502
- Record from opening duplicate connections to the same database.
1503
-
1504
- *Eileen M. Uchitelle*, *John Crepezzi*
1505
-
1506
- * Support hash config for `structure_dump_flags` and `structure_load_flags` flags.
1507
- Now that Active Record supports multiple databases configuration,
1508
- we need a way to pass specific flags for dump/load databases since
1509
- the options are not the same for different adapters.
1510
- We can use in the original way:
865
+ The attributes to be included in the output of `inspect` can be configured with
866
+ `ActiveRecord::Core#attributes_for_inspect`.
1511
867
 
1512
868
  ```ruby
1513
- ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = ['--no-defaults', '--skip-add-drop-table']
1514
- # or
1515
- ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = '--no-defaults --skip-add-drop-table'
869
+ Post.attributes_for_inspect = [:id, :title]
870
+ Post.first.inspect #=> "#<Post id: 1, title: "Hello, World!">"
1516
871
  ```
1517
872
 
1518
- And also use it passing a hash, with one or more keys, where the key
1519
- is the adapter
873
+ With `attributes_for_inspect` set to `:all`, `inspect` will list all the record's attributes.
1520
874
 
1521
875
  ```ruby
1522
- ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = {
1523
- mysql2: ['--no-defaults', '--skip-add-drop-table'],
1524
- postgres: '--no-tablespaces'
1525
- }
876
+ Post.attributes_for_inspect = :all
877
+ Post.first.inspect #=> "#<Post id: 1, title: "Hello, World!", published_at: "2023-10-23 14:28:11 +0000">"
1526
878
  ```
1527
879
 
1528
- *Gustavo Gonzalez*
880
+ In `development` and `test` mode, `attributes_for_inspect` will be set to `:all` by default.
1529
881
 
1530
- * Connection specification now passes the "url" key as a configuration for the
1531
- adapter if the "url" protocol is "jdbc", "http", or "https". Previously only
1532
- urls with the "jdbc" prefix were passed to the Active Record Adapter, others
1533
- are assumed to be adapter specification urls.
882
+ You can also call `full_inspect` to get an inspection with all the attributes.
1534
883
 
1535
- Fixes #41137.
884
+ The attributes in `attribute_for_inspect` will also be used for `pretty_print`.
1536
885
 
1537
- *Jonathan Bracy*
886
+ *Andrew Novoselac*
1538
887
 
1539
- * Allow to opt-out of `strict_loading` mode on a per-record base.
888
+ * Don't mark attributes as changed when reassigned to `Float::INFINITY` or
889
+ `-Float::INFINITY`.
1540
890
 
1541
- This is useful when strict loading is enabled application wide or on a
1542
- model level.
891
+ *Maicol Bentancor*
1543
892
 
1544
- ```ruby
1545
- class User < ApplicationRecord
1546
- has_many :bookmarks
1547
- has_many :articles, strict_loading: true
1548
- end
1549
-
1550
- user = User.first
1551
- user.articles # => ActiveRecord::StrictLoadingViolationError
1552
- user.bookmarks # => #<ActiveRecord::Associations::CollectionProxy>
893
+ * Support the `RETURNING` clause for MariaDB.
1553
894
 
1554
- user.strict_loading!(true) # => true
1555
- user.bookmarks # => ActiveRecord::StrictLoadingViolationError
895
+ *fatkodima*, *Nikolay Kondratyev*
1556
896
 
1557
- user.strict_loading!(false) # => false
1558
- user.bookmarks # => #<ActiveRecord::Associations::CollectionProxy>
1559
- user.articles.strict_loading!(false) # => #<ActiveRecord::Associations::CollectionProxy>
1560
- ```
897
+ * The SQLite3 adapter now implements the `supports_deferrable_constraints?` contract.
1561
898
 
1562
- *Ayrton De Craene*
1563
-
1564
- * Add `FinderMethods#sole` and `#find_sole_by` to find and assert the
1565
- presence of exactly one record.
1566
-
1567
- Used when you need a single row, but also want to assert that there aren't
1568
- multiple rows matching the condition; especially for when database
1569
- constraints aren't enough or are impractical.
899
+ Allows foreign keys to be deferred by adding the `:deferrable` key to the `foreign_key` options.
1570
900
 
1571
901
  ```ruby
1572
- Product.where(["price = %?", price]).sole
1573
- # => ActiveRecord::RecordNotFound (if no Product with given price)
1574
- # => #<Product ...> (if one Product with given price)
1575
- # => ActiveRecord::SoleRecordExceeded (if more than one Product with given price)
1576
-
1577
- user.api_keys.find_sole_by(key: key)
1578
- # as above
902
+ add_reference :person, :alias, foreign_key: { deferrable: :deferred }
903
+ add_reference :alias, :person, foreign_key: { deferrable: :deferred }
1579
904
  ```
1580
905
 
1581
- *Asherah Connor*
906
+ *Stephen Margheim*
1582
907
 
1583
- * Makes `ActiveRecord::AttributeMethods::Query` respect the getter overrides defined in the model.
1584
-
1585
- Before:
908
+ * Add the `set_constraints` helper to PostgreSQL connections.
1586
909
 
1587
910
  ```ruby
1588
- class User
1589
- def admin
1590
- false # Overriding the getter to always return false
1591
- end
1592
- end
1593
-
1594
- user = User.first
1595
- user.update(admin: true)
1596
-
1597
- user.admin # false (as expected, due to the getter overwrite)
1598
- user.admin? # true (not expected, returned the DB column value)
1599
- ```
1600
-
1601
- After this commit, `user.admin?` above returns false, as expected.
1602
-
1603
- Fixes #40771.
1604
-
1605
- *Felipe*
1606
-
1607
- * Allow delegated_type to be specified primary_key and foreign_key.
911
+ Post.create!(user_id: -1) # => ActiveRecord::InvalidForeignKey
1608
912
 
1609
- Since delegated_type assumes that the foreign_key ends with `_id`,
1610
- `singular_id` defined by it does not work when the foreign_key does
1611
- not end with `id`. This change fixes it by taking into account
1612
- `primary_key` and `foreign_key` in the options.
1613
-
1614
- *Ryota Egusa*
1615
-
1616
- * Expose an `invert_where` method that will invert all scope conditions.
1617
-
1618
- ```ruby
1619
- class User
1620
- scope :active, -> { where(accepted: true, locked: false) }
913
+ Post.transaction do
914
+ Post.connection.set_constraints(:deferred)
915
+ p = Post.create!(user_id: -1)
916
+ u = User.create!
917
+ p.user = u
918
+ p.save!
1621
919
  end
1622
-
1623
- User.active
1624
- # ... WHERE `accepted` = 1 AND `locked` = 0
1625
-
1626
- User.active.invert_where
1627
- # ... WHERE NOT (`accepted` = 1 AND `locked` = 0)
1628
920
  ```
1629
921
 
1630
- *Kevin Deisz*
922
+ *Cody Cutrer*
1631
923
 
1632
- * Restore possibility of passing `false` to :polymorphic option of `belongs_to`.
924
+ * Include `ActiveModel::API` in `ActiveRecord::Base`.
1633
925
 
1634
- Previously, passing `false` would trigger the option validation logic
1635
- to throw an error saying :polymorphic would not be a valid option.
926
+ *Sean Doyle*
1636
927
 
1637
- *glaszig*
928
+ * Ensure `#signed_id` outputs `url_safe` strings.
1638
929
 
1639
- * Remove deprecated `database` kwarg from `connected_to`.
930
+ *Jason Meller*
1640
931
 
1641
- *Eileen M. Uchitelle*, *John Crepezzi*
932
+ * Add `nulls_last` and working `desc.nulls_first` for MySQL.
1642
933
 
1643
- * Allow adding nonnamed expression indexes to be revertible.
934
+ *Tristan Fellows*
1644
935
 
1645
- Previously, the following code would raise an error, when executed while rolling back,
1646
- and the index name should be specified explicitly. Now, the index name is inferred
1647
- automatically.
936
+ * Allow for more complex hash arguments for `order` which mimics `where` in `ActiveRecord::Relation`.
1648
937
 
1649
938
  ```ruby
1650
- add_index(:items, "to_tsvector('english', description)")
939
+ Topic.includes(:posts).order(posts: { created_at: :desc })
1651
940
  ```
1652
941
 
1653
- Fixes #40732.
1654
-
1655
- *fatkodima*
1656
-
1657
- * Only warn about negative enums if a positive form that would cause conflicts exists.
1658
-
1659
- Fixes #39065.
1660
-
1661
- *Alex Ghiculescu*
1662
-
1663
- * Add option to run `default_scope` on all queries.
1664
-
1665
- 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`).
1666
-
1667
- 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.
1668
-
1669
- ```ruby
1670
- class Article < ApplicationRecord
1671
- default_scope -> { where(blog_id: Current.blog.id) }, all_queries: true
1672
- end
1673
- ```
1674
-
1675
- *Eileen M. Uchitelle*
1676
-
1677
- * Add `where.associated` to check for the presence of an association.
1678
-
1679
- ```ruby
1680
- # Before:
1681
- account.users.joins(:contact).where.not(contact_id: nil)
1682
-
1683
- # After:
1684
- account.users.where.associated(:contact)
1685
- ```
1686
-
1687
- Also mirrors `where.missing`.
1688
-
1689
- *Kasper Timm Hansen*
1690
-
1691
- * Allow constructors (`build_association` and `create_association`) on
1692
- `has_one :through` associations.
1693
-
1694
- *Santiago Perez Perret*
1695
-
942
+ *Myles Boone*
1696
943
 
1697
- Please check [6-1-stable](https://github.com/rails/rails/blob/6-1-stable/activerecord/CHANGELOG.md) for previous changes.
944
+ Please check [7-1-stable](https://github.com/rails/rails/blob/7-1-stable/activerecord/CHANGELOG.md) for previous changes.