activerecord 6.1.7 → 7.2.2

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 (333) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +616 -1290
  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 +17 -14
  7. data/lib/active_record/association_relation.rb +2 -12
  8. data/lib/active_record/associations/alias_tracker.rb +25 -19
  9. data/lib/active_record/associations/association.rb +60 -21
  10. data/lib/active_record/associations/association_scope.rb +17 -12
  11. data/lib/active_record/associations/belongs_to_association.rb +37 -11
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -4
  13. data/lib/active_record/associations/builder/association.rb +11 -5
  14. data/lib/active_record/associations/builder/belongs_to.rb +41 -14
  15. data/lib/active_record/associations/builder/collection_association.rb +10 -3
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
  17. data/lib/active_record/associations/builder/has_many.rb +4 -4
  18. data/lib/active_record/associations/builder/has_one.rb +4 -4
  19. data/lib/active_record/associations/builder/singular_association.rb +6 -2
  20. data/lib/active_record/associations/collection_association.rb +46 -36
  21. data/lib/active_record/associations/collection_proxy.rb +44 -16
  22. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  23. data/lib/active_record/associations/errors.rb +265 -0
  24. data/lib/active_record/associations/foreign_association.rb +10 -3
  25. data/lib/active_record/associations/has_many_association.rb +29 -19
  26. data/lib/active_record/associations/has_many_through_association.rb +19 -8
  27. data/lib/active_record/associations/has_one_association.rb +20 -10
  28. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  29. data/lib/active_record/associations/join_dependency/join_association.rb +30 -27
  30. data/lib/active_record/associations/join_dependency.rb +28 -20
  31. data/lib/active_record/associations/nested_error.rb +47 -0
  32. data/lib/active_record/associations/preloader/association.rb +212 -53
  33. data/lib/active_record/associations/preloader/batch.rb +48 -0
  34. data/lib/active_record/associations/preloader/branch.rb +153 -0
  35. data/lib/active_record/associations/preloader/through_association.rb +50 -16
  36. data/lib/active_record/associations/preloader.rb +50 -121
  37. data/lib/active_record/associations/singular_association.rb +15 -3
  38. data/lib/active_record/associations/through_association.rb +25 -14
  39. data/lib/active_record/associations.rb +429 -522
  40. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  41. data/lib/active_record/attribute_assignment.rb +1 -5
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
  43. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  44. data/lib/active_record/attribute_methods/dirty.rb +73 -22
  45. data/lib/active_record/attribute_methods/primary_key.rb +47 -27
  46. data/lib/active_record/attribute_methods/query.rb +31 -19
  47. data/lib/active_record/attribute_methods/read.rb +14 -11
  48. data/lib/active_record/attribute_methods/serialization.rb +174 -37
  49. data/lib/active_record/attribute_methods/time_zone_conversion.rb +15 -9
  50. data/lib/active_record/attribute_methods/write.rb +12 -15
  51. data/lib/active_record/attribute_methods.rb +164 -52
  52. data/lib/active_record/attributes.rb +57 -54
  53. data/lib/active_record/autosave_association.rb +74 -57
  54. data/lib/active_record/base.rb +27 -5
  55. data/lib/active_record/callbacks.rb +19 -35
  56. data/lib/active_record/coders/column_serializer.rb +61 -0
  57. data/lib/active_record/coders/json.rb +1 -1
  58. data/lib/active_record/coders/yaml_column.rb +70 -46
  59. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +284 -0
  60. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
  61. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +79 -0
  62. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +325 -604
  63. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
  64. data/lib/active_record/connection_adapters/abstract/database_statements.rb +199 -60
  65. data/lib/active_record/connection_adapters/abstract/query_cache.rb +230 -64
  66. data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -131
  67. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  68. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
  69. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
  70. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
  71. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +378 -143
  72. data/lib/active_record/connection_adapters/abstract/transaction.rb +361 -76
  73. data/lib/active_record/connection_adapters/abstract_adapter.rb +624 -163
  74. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +348 -165
  75. data/lib/active_record/connection_adapters/column.rb +13 -0
  76. data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
  77. data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -130
  78. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -55
  79. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
  80. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
  81. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
  82. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +45 -14
  83. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
  84. data/lib/active_record/connection_adapters/mysql2_adapter.rb +107 -68
  85. data/lib/active_record/connection_adapters/pool_config.rb +26 -16
  86. data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
  87. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
  88. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +114 -54
  89. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
  94. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
  95. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
  96. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +12 -3
  97. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  100. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
  101. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  102. data/lib/active_record/connection_adapters/postgresql/quoting.rb +137 -104
  103. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
  104. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
  105. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +173 -3
  106. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
  107. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +403 -77
  108. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
  109. data/lib/active_record/connection_adapters/postgresql_adapter.rb +520 -253
  110. data/lib/active_record/connection_adapters/schema_cache.rb +326 -102
  111. data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
  112. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +78 -55
  113. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +68 -54
  114. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  115. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
  116. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
  117. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +66 -22
  118. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +372 -130
  119. data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
  120. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
  121. data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
  122. data/lib/active_record/connection_adapters.rb +130 -6
  123. data/lib/active_record/connection_handling.rb +132 -146
  124. data/lib/active_record/core.rb +310 -253
  125. data/lib/active_record/counter_cache.rb +68 -34
  126. data/lib/active_record/database_configurations/connection_url_resolver.rb +10 -4
  127. data/lib/active_record/database_configurations/database_config.rb +34 -10
  128. data/lib/active_record/database_configurations/hash_config.rb +107 -31
  129. data/lib/active_record/database_configurations/url_config.rb +38 -13
  130. data/lib/active_record/database_configurations.rb +96 -60
  131. data/lib/active_record/delegated_type.rb +90 -20
  132. data/lib/active_record/deprecator.rb +7 -0
  133. data/lib/active_record/destroy_association_async_job.rb +4 -2
  134. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  135. data/lib/active_record/dynamic_matchers.rb +3 -3
  136. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  137. data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
  138. data/lib/active_record/encryption/cipher.rb +53 -0
  139. data/lib/active_record/encryption/config.rb +68 -0
  140. data/lib/active_record/encryption/configurable.rb +60 -0
  141. data/lib/active_record/encryption/context.rb +42 -0
  142. data/lib/active_record/encryption/contexts.rb +76 -0
  143. data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
  144. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  145. data/lib/active_record/encryption/encryptable_record.rb +230 -0
  146. data/lib/active_record/encryption/encrypted_attribute_type.rb +175 -0
  147. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  148. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  149. data/lib/active_record/encryption/encryptor.rb +170 -0
  150. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  151. data/lib/active_record/encryption/errors.rb +15 -0
  152. data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
  153. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  154. data/lib/active_record/encryption/key.rb +28 -0
  155. data/lib/active_record/encryption/key_generator.rb +53 -0
  156. data/lib/active_record/encryption/key_provider.rb +46 -0
  157. data/lib/active_record/encryption/message.rb +33 -0
  158. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  159. data/lib/active_record/encryption/message_serializer.rb +96 -0
  160. data/lib/active_record/encryption/null_encryptor.rb +25 -0
  161. data/lib/active_record/encryption/properties.rb +76 -0
  162. data/lib/active_record/encryption/read_only_null_encryptor.rb +28 -0
  163. data/lib/active_record/encryption/scheme.rb +100 -0
  164. data/lib/active_record/encryption.rb +58 -0
  165. data/lib/active_record/enum.rb +170 -62
  166. data/lib/active_record/errors.rb +210 -27
  167. data/lib/active_record/explain.rb +21 -12
  168. data/lib/active_record/explain_registry.rb +11 -6
  169. data/lib/active_record/explain_subscriber.rb +1 -1
  170. data/lib/active_record/fixture_set/file.rb +15 -1
  171. data/lib/active_record/fixture_set/model_metadata.rb +14 -4
  172. data/lib/active_record/fixture_set/render_context.rb +2 -0
  173. data/lib/active_record/fixture_set/table_row.rb +70 -14
  174. data/lib/active_record/fixture_set/table_rows.rb +4 -4
  175. data/lib/active_record/fixtures.rb +179 -112
  176. data/lib/active_record/future_result.rb +178 -0
  177. data/lib/active_record/gem_version.rb +4 -4
  178. data/lib/active_record/inheritance.rb +85 -31
  179. data/lib/active_record/insert_all.rb +148 -32
  180. data/lib/active_record/integration.rb +14 -10
  181. data/lib/active_record/internal_metadata.rb +123 -23
  182. data/lib/active_record/legacy_yaml_adapter.rb +2 -39
  183. data/lib/active_record/locking/optimistic.rb +43 -27
  184. data/lib/active_record/locking/pessimistic.rb +15 -6
  185. data/lib/active_record/log_subscriber.rb +41 -29
  186. data/lib/active_record/marshalling.rb +59 -0
  187. data/lib/active_record/message_pack.rb +124 -0
  188. data/lib/active_record/middleware/database_selector/resolver.rb +10 -10
  189. data/lib/active_record/middleware/database_selector.rb +23 -13
  190. data/lib/active_record/middleware/shard_selector.rb +62 -0
  191. data/lib/active_record/migration/command_recorder.rb +113 -16
  192. data/lib/active_record/migration/compatibility.rb +235 -46
  193. data/lib/active_record/migration/default_strategy.rb +22 -0
  194. data/lib/active_record/migration/execution_strategy.rb +19 -0
  195. data/lib/active_record/migration/join_table.rb +1 -1
  196. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  197. data/lib/active_record/migration.rb +374 -177
  198. data/lib/active_record/model_schema.rb +145 -158
  199. data/lib/active_record/nested_attributes.rb +61 -23
  200. data/lib/active_record/no_touching.rb +3 -3
  201. data/lib/active_record/normalization.rb +163 -0
  202. data/lib/active_record/persistence.rb +282 -283
  203. data/lib/active_record/promise.rb +84 -0
  204. data/lib/active_record/query_cache.rb +18 -25
  205. data/lib/active_record/query_logs.rb +189 -0
  206. data/lib/active_record/query_logs_formatter.rb +41 -0
  207. data/lib/active_record/querying.rb +44 -9
  208. data/lib/active_record/railtie.rb +229 -71
  209. data/lib/active_record/railties/controller_runtime.rb +25 -11
  210. data/lib/active_record/railties/databases.rake +189 -256
  211. data/lib/active_record/railties/job_runtime.rb +23 -0
  212. data/lib/active_record/readonly_attributes.rb +41 -3
  213. data/lib/active_record/reflection.rb +332 -103
  214. data/lib/active_record/relation/batches/batch_enumerator.rb +38 -9
  215. data/lib/active_record/relation/batches.rb +200 -65
  216. data/lib/active_record/relation/calculations.rb +301 -112
  217. data/lib/active_record/relation/delegation.rb +33 -22
  218. data/lib/active_record/relation/finder_methods.rb +123 -52
  219. data/lib/active_record/relation/merger.rb +26 -19
  220. data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
  221. data/lib/active_record/relation/predicate_builder/association_query_value.rb +38 -4
  222. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
  223. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  224. data/lib/active_record/relation/predicate_builder.rb +29 -22
  225. data/lib/active_record/relation/query_attribute.rb +30 -12
  226. data/lib/active_record/relation/query_methods.rb +870 -163
  227. data/lib/active_record/relation/record_fetch_warning.rb +10 -9
  228. data/lib/active_record/relation/spawn_methods.rb +7 -6
  229. data/lib/active_record/relation/where_clause.rb +15 -36
  230. data/lib/active_record/relation.rb +736 -145
  231. data/lib/active_record/result.rb +67 -54
  232. data/lib/active_record/runtime_registry.rb +71 -13
  233. data/lib/active_record/sanitization.rb +84 -34
  234. data/lib/active_record/schema.rb +39 -23
  235. data/lib/active_record/schema_dumper.rb +90 -31
  236. data/lib/active_record/schema_migration.rb +74 -23
  237. data/lib/active_record/scoping/default.rb +72 -15
  238. data/lib/active_record/scoping/named.rb +6 -13
  239. data/lib/active_record/scoping.rb +65 -34
  240. data/lib/active_record/secure_password.rb +60 -0
  241. data/lib/active_record/secure_token.rb +21 -3
  242. data/lib/active_record/serialization.rb +6 -1
  243. data/lib/active_record/signed_id.rb +30 -9
  244. data/lib/active_record/statement_cache.rb +7 -7
  245. data/lib/active_record/store.rb +10 -10
  246. data/lib/active_record/suppressor.rb +13 -15
  247. data/lib/active_record/table_metadata.rb +7 -3
  248. data/lib/active_record/tasks/database_tasks.rb +288 -149
  249. data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
  250. data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
  251. data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -7
  252. data/lib/active_record/test_databases.rb +1 -1
  253. data/lib/active_record/test_fixtures.rb +173 -155
  254. data/lib/active_record/testing/query_assertions.rb +121 -0
  255. data/lib/active_record/timestamp.rb +32 -19
  256. data/lib/active_record/token_for.rb +123 -0
  257. data/lib/active_record/touch_later.rb +12 -7
  258. data/lib/active_record/transaction.rb +132 -0
  259. data/lib/active_record/transactions.rb +118 -41
  260. data/lib/active_record/translation.rb +3 -5
  261. data/lib/active_record/type/adapter_specific_registry.rb +32 -14
  262. data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
  263. data/lib/active_record/type/internal/timezone.rb +7 -2
  264. data/lib/active_record/type/serialized.rb +9 -7
  265. data/lib/active_record/type/time.rb +4 -0
  266. data/lib/active_record/type/type_map.rb +17 -20
  267. data/lib/active_record/type.rb +1 -2
  268. data/lib/active_record/type_caster/connection.rb +4 -4
  269. data/lib/active_record/validations/absence.rb +1 -1
  270. data/lib/active_record/validations/associated.rb +13 -7
  271. data/lib/active_record/validations/numericality.rb +5 -4
  272. data/lib/active_record/validations/presence.rb +5 -28
  273. data/lib/active_record/validations/uniqueness.rb +65 -15
  274. data/lib/active_record/validations.rb +12 -5
  275. data/lib/active_record/version.rb +1 -1
  276. data/lib/active_record.rb +444 -32
  277. data/lib/arel/alias_predication.rb +1 -1
  278. data/lib/arel/attributes/attribute.rb +0 -8
  279. data/lib/arel/collectors/bind.rb +2 -0
  280. data/lib/arel/collectors/composite.rb +7 -0
  281. data/lib/arel/collectors/sql_string.rb +1 -1
  282. data/lib/arel/collectors/substitute_binds.rb +1 -1
  283. data/lib/arel/crud.rb +28 -22
  284. data/lib/arel/delete_manager.rb +18 -4
  285. data/lib/arel/errors.rb +10 -0
  286. data/lib/arel/factory_methods.rb +4 -0
  287. data/lib/arel/filter_predications.rb +9 -0
  288. data/lib/arel/insert_manager.rb +2 -3
  289. data/lib/arel/nodes/binary.rb +6 -7
  290. data/lib/arel/nodes/bound_sql_literal.rb +65 -0
  291. data/lib/arel/nodes/casted.rb +1 -1
  292. data/lib/arel/nodes/cte.rb +36 -0
  293. data/lib/arel/nodes/delete_statement.rb +12 -13
  294. data/lib/arel/nodes/filter.rb +10 -0
  295. data/lib/arel/nodes/fragments.rb +35 -0
  296. data/lib/arel/nodes/function.rb +1 -0
  297. data/lib/arel/nodes/homogeneous_in.rb +1 -9
  298. data/lib/arel/nodes/insert_statement.rb +2 -2
  299. data/lib/arel/nodes/leading_join.rb +8 -0
  300. data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
  301. data/lib/arel/nodes/node.rb +115 -5
  302. data/lib/arel/nodes/select_core.rb +2 -2
  303. data/lib/arel/nodes/select_statement.rb +2 -2
  304. data/lib/arel/nodes/sql_literal.rb +13 -0
  305. data/lib/arel/nodes/table_alias.rb +4 -0
  306. data/lib/arel/nodes/update_statement.rb +8 -3
  307. data/lib/arel/nodes.rb +7 -2
  308. data/lib/arel/predications.rb +14 -4
  309. data/lib/arel/select_manager.rb +11 -5
  310. data/lib/arel/table.rb +9 -6
  311. data/lib/arel/tree_manager.rb +8 -15
  312. data/lib/arel/update_manager.rb +20 -5
  313. data/lib/arel/visitors/dot.rb +81 -90
  314. data/lib/arel/visitors/mysql.rb +23 -5
  315. data/lib/arel/visitors/postgresql.rb +1 -22
  316. data/lib/arel/visitors/sqlite.rb +25 -0
  317. data/lib/arel/visitors/to_sql.rb +170 -36
  318. data/lib/arel/visitors/visitor.rb +2 -2
  319. data/lib/arel.rb +23 -4
  320. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  321. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  322. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
  323. data/lib/rails/generators/active_record/migration.rb +3 -1
  324. data/lib/rails/generators/active_record/model/USAGE +113 -0
  325. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  326. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
  327. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  328. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  329. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  330. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  331. metadata +103 -17
  332. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  333. data/lib/active_record/null_relation.rb +0 -67
@@ -15,6 +15,7 @@ module ActiveRecord
15
15
  # = Active Record Railtie
16
16
  class Railtie < Rails::Railtie # :nodoc:
17
17
  config.active_record = ActiveSupport::OrderedOptions.new
18
+ config.active_record.encryption = ActiveSupport::OrderedOptions.new
18
19
 
19
20
  config.app_generators.orm :active_record, migration: true,
20
21
  timestamps: true
@@ -30,6 +31,13 @@ module ActiveRecord
30
31
  config.active_record.check_schema_cache_dump_version = true
31
32
  config.active_record.maintain_test_schema = true
32
33
  config.active_record.has_many_inversing = false
34
+ config.active_record.query_log_tags_enabled = false
35
+ config.active_record.query_log_tags = [ :application ]
36
+ config.active_record.query_log_tags_format = :legacy
37
+ config.active_record.cache_query_log_tags = false
38
+ config.active_record.raise_on_assign_to_attr_readonly = false
39
+ config.active_record.belongs_to_required_validates_foreign_key = true
40
+ config.active_record.generate_secure_token_on = :create
33
41
 
34
42
  config.active_record.queues = ActiveSupport::InheritableOptions.new
35
43
 
@@ -58,19 +66,31 @@ module ActiveRecord
58
66
  unless ActiveSupport::Logger.logger_outputs_to?(Rails.logger, STDERR, STDOUT)
59
67
  console = ActiveSupport::Logger.new(STDERR)
60
68
  console.level = Rails.logger.level
61
- Rails.logger.extend ActiveSupport::Logger.broadcast console
69
+ Rails.logger.broadcast_to(console)
62
70
  end
63
- ActiveRecord::Base.verbose_query_logs = false
71
+ ActiveRecord.verbose_query_logs = false
72
+ ActiveRecord::Base.attributes_for_inspect = :all
64
73
  end
65
74
 
66
75
  runner do
67
76
  require "active_record/base"
68
77
  end
69
78
 
79
+ initializer "active_record.deprecator", before: :load_environment_config do |app|
80
+ app.deprecators[:active_record] = ActiveRecord.deprecator
81
+ end
82
+
70
83
  initializer "active_record.initialize_timezone" do
71
84
  ActiveSupport.on_load(:active_record) do
72
85
  self.time_zone_aware_attributes = true
73
- self.default_timezone = :utc
86
+ end
87
+ end
88
+
89
+ initializer "active_record.postgresql_time_zone_aware_types" do
90
+ ActiveSupport.on_load(:active_record_postgresqladapter) do
91
+ ActiveSupport.on_load(:active_record) do
92
+ ActiveRecord::Base.time_zone_aware_types << :timestamptz
93
+ end
74
94
  end
75
95
  end
76
96
 
@@ -83,22 +103,14 @@ module ActiveRecord
83
103
  end
84
104
 
85
105
  initializer "active_record.migration_error" do |app|
86
- if config.active_record.delete(:migration_error) == :page_load
106
+ if config.active_record.migration_error == :page_load
87
107
  config.app_middleware.insert_after ::ActionDispatch::Callbacks,
88
108
  ActiveRecord::Migration::CheckPending,
89
109
  file_watcher: app.config.file_watcher
90
110
  end
91
111
  end
92
112
 
93
- initializer "active_record.database_selector" do
94
- if options = config.active_record.delete(:database_selector)
95
- resolver = config.active_record.delete(:database_resolver)
96
- operations = config.active_record.delete(:database_resolver_context)
97
- config.app_middleware.use ActiveRecord::Middleware::DatabaseSelector, resolver, operations, options
98
- end
99
- end
100
-
101
- initializer "Check for cache versioning support" do
113
+ initializer "active_record.cache_versioning_support" do
102
114
  config.after_initialize do |app|
103
115
  ActiveSupport.on_load(:active_record) do
104
116
  if app.config.active_record.cache_versioning && Rails.cache
@@ -123,62 +135,41 @@ To keep using the current cache store, you can turn off cache versioning entirel
123
135
  end
124
136
  end
125
137
 
126
- initializer "active_record.check_schema_cache_dump" do
127
- check_schema_cache_dump_version = config.active_record.delete(:check_schema_cache_dump_version)
128
-
129
- if config.active_record.delete(:use_schema_cache_dump)
130
- config.after_initialize do |app|
131
- ActiveSupport.on_load(:active_record) do
132
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).first
133
-
134
- filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(
135
- db_config.name,
136
- schema_cache_path: db_config&.schema_cache_path
137
- )
138
+ initializer "active_record.copy_schema_cache_config" do
139
+ active_record_config = config.active_record
138
140
 
139
- cache = ActiveRecord::ConnectionAdapters::SchemaCache.load_from(filename)
140
- next if cache.nil?
141
-
142
- if check_schema_cache_dump_version
143
- current_version = begin
144
- ActiveRecord::Migrator.current_version
145
- rescue ActiveRecordError => error
146
- warn "Failed to validate the schema cache because of #{error.class}: #{error.message}"
147
- nil
148
- end
149
- next if current_version.nil?
150
-
151
- if cache.version != current_version
152
- warn "Ignoring #{filename} because it has expired. The current schema version is #{current_version}, but the one in the cache is #{cache.version}."
153
- next
154
- end
155
- end
156
-
157
- connection_pool.set_schema_cache(cache)
158
- end
159
- end
160
- end
141
+ ActiveRecord::ConnectionAdapters::SchemaReflection.use_schema_cache_dump = active_record_config.use_schema_cache_dump
142
+ ActiveRecord::ConnectionAdapters::SchemaReflection.check_schema_cache_dump_version = active_record_config.check_schema_cache_dump_version
161
143
  end
162
144
 
163
145
  initializer "active_record.define_attribute_methods" do |app|
146
+ # For resiliency, it is critical that a Rails application should be
147
+ # able to boot without depending on the database (or any other service)
148
+ # being responsive.
149
+ #
150
+ # Otherwise a bad deploy adding a lot of load on the database may require to
151
+ # entirely shutdown the application so the database can recover before a fixed
152
+ # version can be deployed again.
153
+ #
154
+ # This is why this initializer tries hard not to query the database, and if it
155
+ # does, it makes sure to rescue any possible database error.
156
+ check_schema_cache_dump_version = config.active_record.check_schema_cache_dump_version
164
157
  config.after_initialize do
165
158
  ActiveSupport.on_load(:active_record) do
166
- if app.config.eager_load
159
+ # In development and test we shouldn't eagerly define attribute methods because
160
+ # db:test:prepare will trigger later and might change the schema.
161
+ #
162
+ # Additionally if `check_schema_cache_dump_version` is enabled (which is the default),
163
+ # loading the schema cache dump trigger a database connection to compare the schema
164
+ # versions.
165
+ # This means the attribute methods will be lazily defined when the model is accessed,
166
+ # likely as part of the first few requests or jobs. This isn't good for performance
167
+ # but we unfortunately have to arbitrate between resiliency and performance, and chose
168
+ # resiliency.
169
+ if !check_schema_cache_dump_version && app.config.eager_load && !Rails.env.local?
167
170
  begin
168
171
  descendants.each do |model|
169
- # SchemaMigration and InternalMetadata both override `table_exists?`
170
- # to bypass the schema cache, so skip them to avoid the extra queries.
171
- next if model._internal?
172
-
173
- # If the schema cache was loaded from a dump, we can use it without connecting
174
- schema_cache = model.connection_pool.schema_cache
175
-
176
- # If there's no connection yet, we avoid connecting.
177
- schema_cache ||= model.connected? && model.connection.schema_cache
178
-
179
- # If the schema cache doesn't have the columns
180
- # hash for the model cached, `define_attribute_methods` would trigger a query.
181
- if schema_cache && schema_cache.columns_hash?(model.table_name)
172
+ if model.connection_pool.schema_reflection.cached?(model.table_name)
182
173
  model.define_attribute_methods
183
174
  end
184
175
  end
@@ -195,18 +186,91 @@ To keep using the current cache store, you can turn off cache versioning entirel
195
186
 
196
187
  initializer "active_record.warn_on_records_fetched_greater_than" do
197
188
  if config.active_record.warn_on_records_fetched_greater_than
189
+ ActiveRecord.deprecator.warn <<~MSG.squish
190
+ `config.active_record.warn_on_records_fetched_greater_than` is deprecated and will be
191
+ removed in Rails 8.0.
192
+ Please subscribe to `sql.active_record` notifications and access the row count field to
193
+ detect large result set sizes.
194
+ MSG
198
195
  ActiveSupport.on_load(:active_record) do
199
196
  require "active_record/relation/record_fetch_warning"
200
197
  end
201
198
  end
202
199
  end
203
200
 
201
+ initializer "active_record.sqlite3_deprecated_warning" do
202
+ if config.active_record.key?(:sqlite3_production_warning)
203
+ config.active_record.delete(:sqlite3_production_warning)
204
+ ActiveRecord.deprecator.warn <<~MSG.squish
205
+ The `config.active_record.sqlite3_production_warning` configuration no longer has any effect
206
+ and can be safely removed.
207
+ MSG
208
+ end
209
+ end
210
+
211
+ initializer "active_record.sqlite3_adapter_strict_strings_by_default" do
212
+ config.after_initialize do
213
+ if config.active_record.sqlite3_adapter_strict_strings_by_default
214
+ ActiveSupport.on_load(:active_record_sqlite3adapter) do
215
+ self.strict_strings_by_default = true
216
+ end
217
+ end
218
+ end
219
+ end
220
+
221
+ initializer "active_record.postgresql_adapter_decode_dates" do
222
+ config.after_initialize do
223
+ if config.active_record.postgresql_adapter_decode_dates
224
+ ActiveSupport.on_load(:active_record_postgresqladapter) do
225
+ self.decode_dates = true
226
+ end
227
+ end
228
+ end
229
+ end
230
+
204
231
  initializer "active_record.set_configs" do |app|
205
- ActiveSupport.on_load(:active_record) do
206
- configs = app.config.active_record
232
+ configs = app.config.active_record
207
233
 
234
+ config.after_initialize do
208
235
  configs.each do |k, v|
209
- send "#{k}=", v
236
+ next if k == :encryption
237
+ setter = "#{k}="
238
+ if ActiveRecord.respond_to?(setter)
239
+ ActiveRecord.send(setter, v)
240
+ end
241
+ end
242
+ end
243
+
244
+ ActiveSupport.on_load(:active_record) do
245
+ configs_used_in_other_initializers = configs.except(
246
+ :migration_error,
247
+ :database_selector,
248
+ :database_resolver,
249
+ :database_resolver_context,
250
+ :shard_selector,
251
+ :shard_resolver,
252
+ :query_log_tags_enabled,
253
+ :query_log_tags,
254
+ :query_log_tags_format,
255
+ :cache_query_log_tags,
256
+ :sqlite3_adapter_strict_strings_by_default,
257
+ :check_schema_cache_dump_version,
258
+ :use_schema_cache_dump,
259
+ :postgresql_adapter_decode_dates,
260
+ )
261
+
262
+ configs_used_in_other_initializers.each do |k, v|
263
+ next if k == :encryption
264
+ setter = "#{k}="
265
+ # Some existing initializers might rely on Active Record configuration
266
+ # being copied from the config object to their actual destination when
267
+ # `ActiveRecord::Base` is loaded.
268
+ # So to preserve backward compatibility we copy the config a second time.
269
+ if ActiveRecord.respond_to?(setter)
270
+ ActiveRecord.send(setter, v)
271
+ else
272
+ send(setter, v)
273
+ end
210
274
  end
211
275
  end
212
276
  end
@@ -215,20 +279,23 @@ To keep using the current cache store, you can turn off cache versioning entirel
215
279
  # and then establishes the connection.
216
280
  initializer "active_record.initialize_database" do
217
281
  ActiveSupport.on_load(:active_record) do
218
- if ActiveRecord::Base.legacy_connection_handling
219
- self.connection_handlers = { writing_role => ActiveRecord::Base.default_connection_handler }
220
- end
221
282
  self.configurations = Rails.application.config.database_configuration
283
+
222
284
  establish_connection
223
285
  end
224
286
  end
225
287
 
226
- # Expose database runtime to controller for logging.
288
+ # Expose database runtime for logging.
227
289
  initializer "active_record.log_runtime" do
228
290
  require "active_record/railties/controller_runtime"
229
291
  ActiveSupport.on_load(:action_controller) do
230
292
  include ActiveRecord::Railties::ControllerRuntime
231
293
  end
294
+
295
+ require "active_record/railties/job_runtime"
296
+ ActiveSupport.on_load(:active_job) do
297
+ include ActiveRecord::Railties::JobRuntime
298
+ end
232
299
  end
233
300
 
234
301
  initializer "active_record.set_reloader_hooks" do
@@ -236,7 +303,7 @@ To keep using the current cache store, you can turn off cache versioning entirel
236
303
  ActiveSupport::Reloader.before_class_unload do
237
304
  if ActiveRecord::Base.connected?
238
305
  ActiveRecord::Base.clear_cache!
239
- ActiveRecord::Base.clear_reloadable_connections!
306
+ ActiveRecord::Base.connection_handler.clear_reloadable_connections!(:all)
240
307
  end
241
308
  end
242
309
  end
@@ -244,6 +311,8 @@ To keep using the current cache store, you can turn off cache versioning entirel
244
311
 
245
312
  initializer "active_record.set_executor_hooks" do
246
313
  ActiveRecord::QueryCache.install_executor_hooks
314
+ ActiveRecord::AsynchronousQueriesTracker.install_executor_hooks
315
+ ActiveRecord::ConnectionAdapters::ConnectionPool.install_executor_hooks
247
316
  end
248
317
 
249
318
  initializer "active_record.add_watchable_files" do |app|
@@ -262,8 +331,8 @@ To keep using the current cache store, you can turn off cache versioning entirel
262
331
  # this connection is trivial: the rest of the pool would need to be
263
332
  # populated anyway.
264
333
 
265
- clear_active_connections!
266
- flush_idle_connections!
334
+ connection_handler.clear_active_connections!(:all)
335
+ connection_handler.flush_idle_connections!(:all)
267
336
  end
268
337
  end
269
338
  end
@@ -279,5 +348,94 @@ To keep using the current cache store, you can turn off cache versioning entirel
279
348
  self.signed_id_verifier_secret ||= -> { Rails.application.key_generator.generate_key("active_record/signed_id") }
280
349
  end
281
350
  end
351
+
352
+ initializer "active_record.generated_token_verifier" do
353
+ config.after_initialize do |app|
354
+ ActiveSupport.on_load(:active_record) do
355
+ self.generated_token_verifier ||= app.message_verifier("active_record/token_for")
356
+ end
357
+ end
358
+ end
359
+
360
+ initializer "active_record_encryption.configuration" do |app|
361
+ ActiveSupport.on_load(:active_record_encryption) do
362
+ ActiveRecord::Encryption.configure(
363
+ primary_key: app.credentials.dig(:active_record_encryption, :primary_key),
364
+ deterministic_key: app.credentials.dig(:active_record_encryption, :deterministic_key),
365
+ key_derivation_salt: app.credentials.dig(:active_record_encryption, :key_derivation_salt),
366
+ **app.config.active_record.encryption
367
+ )
368
+
369
+ auto_filtered_parameters = ActiveRecord::Encryption::AutoFilteredParameters.new(app)
370
+ auto_filtered_parameters.enable if ActiveRecord::Encryption.config.add_to_filter_parameters
371
+ end
372
+
373
+ ActiveSupport.on_load(:active_record) do
374
+ # Support extended queries for deterministic attributes and validations
375
+ if ActiveRecord::Encryption.config.extend_queries
376
+ ActiveRecord::Encryption::ExtendedDeterministicQueries.install_support
377
+ ActiveRecord::Encryption::ExtendedDeterministicUniquenessValidator.install_support
378
+ end
379
+ end
380
+
381
+ ActiveSupport.on_load(:active_record_fixture_set) do
382
+ # Encrypt Active Record fixtures
383
+ if ActiveRecord::Encryption.config.encrypt_fixtures
384
+ ActiveRecord::Fixture.prepend ActiveRecord::Encryption::EncryptedFixtures
385
+ end
386
+ end
387
+ end
388
+
389
+ initializer "active_record.query_log_tags_config" do |app|
390
+ config.after_initialize do
391
+ if app.config.active_record.query_log_tags_enabled
392
+ ActiveRecord.query_transformers << ActiveRecord::QueryLogs
393
+ ActiveRecord::QueryLogs.taggings.merge!(
394
+ application: Rails.application.class.name.split("::").first,
395
+ pid: -> { Process.pid.to_s },
396
+ socket: ->(context) { context[:connection].pool.db_config.socket },
397
+ db_host: ->(context) { context[:connection].pool.db_config.host },
398
+ database: ->(context) { context[:connection].pool.db_config.database },
399
+ source_location: -> { QueryLogs.query_source_location }
400
+ )
401
+ ActiveRecord.disable_prepared_statements = true
402
+
403
+ if app.config.active_record.query_log_tags.present?
404
+ ActiveRecord::QueryLogs.tags = app.config.active_record.query_log_tags
405
+ end
406
+
407
+ if app.config.active_record.query_log_tags_format
408
+ ActiveRecord::QueryLogs.update_formatter(app.config.active_record.query_log_tags_format)
409
+ end
410
+
411
+ if app.config.active_record.cache_query_log_tags
412
+ ActiveRecord::QueryLogs.cache_query_log_tags = true
413
+ end
414
+ end
415
+ end
416
+ end
417
+
418
+ initializer "active_record.unregister_current_scopes_on_unload" do |app|
419
+ config.after_initialize do
420
+ if app.config.reloading_enabled?
421
+ Rails.autoloaders.main.on_unload do |_cpath, value, _abspath|
422
+ # Conditions are written this way to be robust against custom
423
+ # implementations of value#is_a? or value#<.
424
+ if Class === value && ActiveRecord::Base > value
425
+ value.current_scope = nil
426
+ end
427
+ end
428
+ end
429
+ end
430
+ end
431
+
432
+ initializer "active_record.message_pack" do
433
+ ActiveSupport.on_load(:message_pack) do
434
+ ActiveSupport.on_load(:active_record) do
435
+ require "active_record/message_pack"
436
+ ActiveRecord::MessagePack::Extensions.install(ActiveSupport::MessagePack::CacheSerializer)
437
+ end
438
+ end
439
+ end
282
440
  end
283
441
  end
@@ -1,21 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/module/attr_internal"
4
- require "active_record/log_subscriber"
4
+ require "active_record/runtime_registry"
5
5
 
6
6
  module ActiveRecord
7
7
  module Railties # :nodoc:
8
- module ControllerRuntime #:nodoc:
8
+ module ControllerRuntime # :nodoc:
9
9
  extend ActiveSupport::Concern
10
10
 
11
11
  module ClassMethods # :nodoc:
12
12
  def log_process_action(payload)
13
13
  messages, db_runtime = super, payload[:db_runtime]
14
- messages << ("ActiveRecord: %.1fms" % db_runtime.to_f) if db_runtime
14
+
15
+ if db_runtime
16
+ queries_count = payload[:queries_count] || 0
17
+ cached_queries_count = payload[:cached_queries_count] || 0
18
+ messages << ("ActiveRecord: %.1fms (%d %s, %d cached)" % [db_runtime.to_f, queries_count,
19
+ "query".pluralize(queries_count), cached_queries_count])
20
+ end
21
+
15
22
  messages
16
23
  end
17
24
  end
18
25
 
26
+ def initialize(...) # :nodoc:
27
+ super
28
+ self.db_runtime = nil
29
+ end
30
+
19
31
  private
20
32
  attr_internal :db_runtime
21
33
 
@@ -23,18 +35,19 @@ module ActiveRecord
23
35
  # We also need to reset the runtime before each action
24
36
  # because of queries in middleware or in cases we are streaming
25
37
  # and it won't be cleaned up by the method below.
26
- ActiveRecord::LogSubscriber.reset_runtime
38
+ ActiveRecord::RuntimeRegistry.reset
27
39
  super
28
40
  end
29
41
 
30
42
  def cleanup_view_runtime
31
- if logger && logger.info? && ActiveRecord::Base.connected?
32
- db_rt_before_render = ActiveRecord::LogSubscriber.reset_runtime
43
+ if logger && logger.info?
44
+ db_rt_before_render = ActiveRecord::RuntimeRegistry.reset_runtimes
33
45
  self.db_runtime = (db_runtime || 0) + db_rt_before_render
34
46
  runtime = super
35
- db_rt_after_render = ActiveRecord::LogSubscriber.reset_runtime
47
+ queries_rt = ActiveRecord::RuntimeRegistry.sql_runtime - ActiveRecord::RuntimeRegistry.async_sql_runtime
48
+ db_rt_after_render = ActiveRecord::RuntimeRegistry.reset_runtimes
36
49
  self.db_runtime += db_rt_after_render
37
- runtime - db_rt_after_render
50
+ runtime - queries_rt
38
51
  else
39
52
  super
40
53
  end
@@ -42,9 +55,10 @@ module ActiveRecord
42
55
 
43
56
  def append_info_to_payload(payload)
44
57
  super
45
- if ActiveRecord::Base.connected?
46
- payload[:db_runtime] = (db_runtime || 0) + ActiveRecord::LogSubscriber.reset_runtime
47
- end
58
+
59
+ payload[:db_runtime] = (db_runtime || 0) + ActiveRecord::RuntimeRegistry.reset_runtimes
60
+ payload[:queries_count] = ActiveRecord::RuntimeRegistry.reset_queries_count
61
+ payload[:cached_queries_count] = ActiveRecord::RuntimeRegistry.reset_cached_queries_count
48
62
  end
49
63
  end
50
64
  end