activerecord 7.0.8 → 7.2.0

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