activerecord 6.1.3.2 → 7.0.0.alpha2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (229) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +734 -1058
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/active_record/aggregations.rb +1 -1
  6. data/lib/active_record/association_relation.rb +0 -10
  7. data/lib/active_record/associations/association.rb +35 -7
  8. data/lib/active_record/associations/association_scope.rb +1 -3
  9. data/lib/active_record/associations/belongs_to_association.rb +16 -6
  10. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
  11. data/lib/active_record/associations/builder/association.rb +8 -2
  12. data/lib/active_record/associations/builder/belongs_to.rb +19 -6
  13. data/lib/active_record/associations/builder/collection_association.rb +1 -1
  14. data/lib/active_record/associations/builder/has_many.rb +3 -2
  15. data/lib/active_record/associations/builder/has_one.rb +2 -1
  16. data/lib/active_record/associations/builder/singular_association.rb +2 -2
  17. data/lib/active_record/associations/collection_association.rb +24 -25
  18. data/lib/active_record/associations/collection_proxy.rb +8 -3
  19. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  20. data/lib/active_record/associations/has_many_association.rb +1 -1
  21. data/lib/active_record/associations/has_many_through_association.rb +2 -1
  22. data/lib/active_record/associations/has_one_association.rb +10 -7
  23. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  24. data/lib/active_record/associations/preloader/association.rb +161 -49
  25. data/lib/active_record/associations/preloader/batch.rb +51 -0
  26. data/lib/active_record/associations/preloader/branch.rb +147 -0
  27. data/lib/active_record/associations/preloader/through_association.rb +37 -11
  28. data/lib/active_record/associations/preloader.rb +46 -110
  29. data/lib/active_record/associations/singular_association.rb +8 -2
  30. data/lib/active_record/associations/through_association.rb +1 -1
  31. data/lib/active_record/associations.rb +76 -81
  32. data/lib/active_record/asynchronous_queries_tracker.rb +57 -0
  33. data/lib/active_record/attribute_assignment.rb +1 -1
  34. data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
  35. data/lib/active_record/attribute_methods/dirty.rb +41 -16
  36. data/lib/active_record/attribute_methods/primary_key.rb +2 -2
  37. data/lib/active_record/attribute_methods/query.rb +2 -2
  38. data/lib/active_record/attribute_methods/read.rb +7 -5
  39. data/lib/active_record/attribute_methods/serialization.rb +66 -12
  40. data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
  41. data/lib/active_record/attribute_methods/write.rb +7 -10
  42. data/lib/active_record/attribute_methods.rb +6 -9
  43. data/lib/active_record/attributes.rb +24 -35
  44. data/lib/active_record/autosave_association.rb +3 -18
  45. data/lib/active_record/base.rb +19 -1
  46. data/lib/active_record/callbacks.rb +2 -2
  47. data/lib/active_record/coders/yaml_column.rb +11 -1
  48. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +312 -0
  49. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
  50. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +31 -558
  52. data/lib/active_record/connection_adapters/abstract/database_statements.rb +45 -21
  53. data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -12
  54. data/lib/active_record/connection_adapters/abstract/quoting.rb +14 -7
  55. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +5 -18
  56. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -9
  57. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +60 -16
  58. data/lib/active_record/connection_adapters/abstract/transaction.rb +17 -6
  59. data/lib/active_record/connection_adapters/abstract_adapter.rb +115 -69
  60. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +96 -81
  61. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +6 -2
  62. data/lib/active_record/connection_adapters/mysql/database_statements.rb +33 -21
  63. data/lib/active_record/connection_adapters/mysql/quoting.rb +16 -1
  64. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +3 -0
  65. data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -6
  66. data/lib/active_record/connection_adapters/pool_config.rb +1 -3
  67. data/lib/active_record/connection_adapters/pool_manager.rb +5 -1
  68. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +19 -12
  69. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
  70. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
  71. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
  72. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
  73. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  74. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +28 -0
  75. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  76. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  77. data/lib/active_record/connection_adapters/postgresql/quoting.rb +6 -6
  78. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +32 -0
  79. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +5 -1
  80. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +12 -12
  81. data/lib/active_record/connection_adapters/postgresql_adapter.rb +157 -100
  82. data/lib/active_record/connection_adapters/schema_cache.rb +35 -4
  83. data/lib/active_record/connection_adapters/sql_type_metadata.rb +0 -2
  84. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +23 -17
  85. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +4 -2
  86. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -30
  87. data/lib/active_record/connection_adapters.rb +8 -5
  88. data/lib/active_record/connection_handling.rb +20 -38
  89. data/lib/active_record/core.rb +129 -117
  90. data/lib/active_record/database_configurations/database_config.rb +12 -0
  91. data/lib/active_record/database_configurations/hash_config.rb +27 -1
  92. data/lib/active_record/database_configurations/url_config.rb +2 -2
  93. data/lib/active_record/database_configurations.rb +18 -9
  94. data/lib/active_record/delegated_type.rb +33 -11
  95. data/lib/active_record/destroy_association_async_job.rb +1 -1
  96. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  97. data/lib/active_record/dynamic_matchers.rb +1 -1
  98. data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
  99. data/lib/active_record/encryption/cipher.rb +53 -0
  100. data/lib/active_record/encryption/config.rb +44 -0
  101. data/lib/active_record/encryption/configurable.rb +61 -0
  102. data/lib/active_record/encryption/context.rb +35 -0
  103. data/lib/active_record/encryption/contexts.rb +72 -0
  104. data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
  105. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  106. data/lib/active_record/encryption/encryptable_record.rb +208 -0
  107. data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
  108. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  109. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  110. data/lib/active_record/encryption/encryptor.rb +155 -0
  111. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  112. data/lib/active_record/encryption/errors.rb +15 -0
  113. data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
  114. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +29 -0
  115. data/lib/active_record/encryption/key.rb +28 -0
  116. data/lib/active_record/encryption/key_generator.rb +42 -0
  117. data/lib/active_record/encryption/key_provider.rb +46 -0
  118. data/lib/active_record/encryption/message.rb +33 -0
  119. data/lib/active_record/encryption/message_serializer.rb +80 -0
  120. data/lib/active_record/encryption/null_encryptor.rb +21 -0
  121. data/lib/active_record/encryption/properties.rb +76 -0
  122. data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
  123. data/lib/active_record/encryption/scheme.rb +99 -0
  124. data/lib/active_record/encryption.rb +55 -0
  125. data/lib/active_record/enum.rb +44 -46
  126. data/lib/active_record/errors.rb +66 -3
  127. data/lib/active_record/fixture_set/file.rb +15 -1
  128. data/lib/active_record/fixture_set/table_row.rb +40 -5
  129. data/lib/active_record/fixture_set/table_rows.rb +4 -4
  130. data/lib/active_record/fixtures.rb +16 -11
  131. data/lib/active_record/future_result.rb +139 -0
  132. data/lib/active_record/gem_version.rb +4 -4
  133. data/lib/active_record/inheritance.rb +55 -17
  134. data/lib/active_record/insert_all.rb +39 -6
  135. data/lib/active_record/integration.rb +1 -1
  136. data/lib/active_record/internal_metadata.rb +3 -5
  137. data/lib/active_record/legacy_yaml_adapter.rb +1 -1
  138. data/lib/active_record/locking/optimistic.rb +10 -9
  139. data/lib/active_record/log_subscriber.rb +6 -2
  140. data/lib/active_record/middleware/database_selector/resolver.rb +6 -10
  141. data/lib/active_record/middleware/database_selector.rb +8 -3
  142. data/lib/active_record/migration/command_recorder.rb +4 -4
  143. data/lib/active_record/migration/compatibility.rb +83 -1
  144. data/lib/active_record/migration/join_table.rb +1 -1
  145. data/lib/active_record/migration.rb +109 -79
  146. data/lib/active_record/model_schema.rb +46 -32
  147. data/lib/active_record/nested_attributes.rb +3 -3
  148. data/lib/active_record/no_touching.rb +2 -2
  149. data/lib/active_record/null_relation.rb +2 -6
  150. data/lib/active_record/persistence.rb +134 -45
  151. data/lib/active_record/query_cache.rb +2 -2
  152. data/lib/active_record/query_logs.rb +203 -0
  153. data/lib/active_record/querying.rb +15 -5
  154. data/lib/active_record/railtie.rb +117 -17
  155. data/lib/active_record/railties/controller_runtime.rb +1 -1
  156. data/lib/active_record/railties/databases.rake +83 -58
  157. data/lib/active_record/readonly_attributes.rb +11 -0
  158. data/lib/active_record/reflection.rb +45 -44
  159. data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
  160. data/lib/active_record/relation/batches.rb +3 -3
  161. data/lib/active_record/relation/calculations.rb +42 -25
  162. data/lib/active_record/relation/delegation.rb +6 -6
  163. data/lib/active_record/relation/finder_methods.rb +32 -23
  164. data/lib/active_record/relation/merger.rb +20 -13
  165. data/lib/active_record/relation/predicate_builder.rb +1 -6
  166. data/lib/active_record/relation/query_attribute.rb +5 -11
  167. data/lib/active_record/relation/query_methods.rb +233 -50
  168. data/lib/active_record/relation/record_fetch_warning.rb +2 -2
  169. data/lib/active_record/relation/spawn_methods.rb +2 -2
  170. data/lib/active_record/relation/where_clause.rb +22 -15
  171. data/lib/active_record/relation.rb +170 -87
  172. data/lib/active_record/result.rb +17 -2
  173. data/lib/active_record/runtime_registry.rb +2 -4
  174. data/lib/active_record/sanitization.rb +11 -7
  175. data/lib/active_record/schema_dumper.rb +3 -3
  176. data/lib/active_record/schema_migration.rb +0 -4
  177. data/lib/active_record/scoping/default.rb +62 -15
  178. data/lib/active_record/scoping/named.rb +3 -11
  179. data/lib/active_record/scoping.rb +40 -22
  180. data/lib/active_record/serialization.rb +1 -1
  181. data/lib/active_record/signed_id.rb +1 -1
  182. data/lib/active_record/statement_cache.rb +2 -2
  183. data/lib/active_record/tasks/database_tasks.rb +107 -23
  184. data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
  185. data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -11
  186. data/lib/active_record/test_databases.rb +1 -1
  187. data/lib/active_record/test_fixtures.rb +45 -4
  188. data/lib/active_record/timestamp.rb +3 -4
  189. data/lib/active_record/transactions.rb +9 -14
  190. data/lib/active_record/translation.rb +2 -2
  191. data/lib/active_record/type/adapter_specific_registry.rb +32 -7
  192. data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
  193. data/lib/active_record/type/internal/timezone.rb +2 -2
  194. data/lib/active_record/type/serialized.rb +1 -1
  195. data/lib/active_record/type/type_map.rb +17 -20
  196. data/lib/active_record/type.rb +1 -2
  197. data/lib/active_record/validations/associated.rb +1 -1
  198. data/lib/active_record/validations/numericality.rb +1 -1
  199. data/lib/active_record.rb +170 -2
  200. data/lib/arel/attributes/attribute.rb +0 -8
  201. data/lib/arel/collectors/bind.rb +2 -2
  202. data/lib/arel/collectors/composite.rb +3 -3
  203. data/lib/arel/collectors/sql_string.rb +1 -1
  204. data/lib/arel/collectors/substitute_binds.rb +1 -1
  205. data/lib/arel/crud.rb +18 -22
  206. data/lib/arel/delete_manager.rb +2 -4
  207. data/lib/arel/insert_manager.rb +2 -3
  208. data/lib/arel/nodes/casted.rb +1 -1
  209. data/lib/arel/nodes/delete_statement.rb +8 -13
  210. data/lib/arel/nodes/homogeneous_in.rb +4 -0
  211. data/lib/arel/nodes/insert_statement.rb +2 -2
  212. data/lib/arel/nodes/select_core.rb +2 -2
  213. data/lib/arel/nodes/select_statement.rb +2 -2
  214. data/lib/arel/nodes/update_statement.rb +3 -2
  215. data/lib/arel/predications.rb +3 -3
  216. data/lib/arel/select_manager.rb +10 -4
  217. data/lib/arel/table.rb +0 -1
  218. data/lib/arel/tree_manager.rb +0 -12
  219. data/lib/arel/update_manager.rb +2 -4
  220. data/lib/arel/visitors/dot.rb +80 -90
  221. data/lib/arel/visitors/mysql.rb +6 -1
  222. data/lib/arel/visitors/postgresql.rb +0 -10
  223. data/lib/arel/visitors/to_sql.rb +44 -3
  224. data/lib/arel.rb +1 -1
  225. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  226. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
  227. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  228. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  229. metadata +55 -16
@@ -134,10 +134,8 @@ module ActiveRecord
134
134
  # ActiveRecord::Base.connected_to(role: :reading, shard: :shard_one_replica) do
135
135
  # Dog.first # finds first Dog record stored on the shard one replica
136
136
  # end
137
- #
138
- # The database kwarg is deprecated and will be removed in 6.2.0 without replacement.
139
- def connected_to(database: nil, role: nil, shard: nil, prevent_writes: false, &blk)
140
- if legacy_connection_handling
137
+ def connected_to(role: nil, shard: nil, prevent_writes: false, &blk)
138
+ if ActiveRecord.legacy_connection_handling
141
139
  if self != Base
142
140
  raise NotImplementedError, "`connected_to` can only be called on ActiveRecord::Base with legacy connection handling."
143
141
  end
@@ -151,31 +149,15 @@ module ActiveRecord
151
149
  end
152
150
  end
153
151
 
154
- if database && (role || shard)
155
- raise ArgumentError, "`connected_to` cannot accept a `database` argument with any other arguments."
156
- elsif database
157
- ActiveSupport::Deprecation.warn("The database key in `connected_to` is deprecated. It will be removed in Rails 6.2.0 without replacement.")
158
-
159
- if database.is_a?(Hash)
160
- role, database = database.first
161
- role = role.to_sym
162
- end
163
-
164
- db_config, owner_name = resolve_config_for_connection(database)
165
- handler = lookup_connection_handler(role)
166
-
167
- handler.establish_connection(db_config, owner_name: owner_name, role: role)
168
-
169
- with_handler(role, &blk)
170
- elsif role || shard
171
- unless role
172
- raise ArgumentError, "`connected_to` cannot accept a `shard` argument without a `role`."
173
- end
174
-
175
- with_role_and_shard(role, shard, prevent_writes, &blk)
176
- else
152
+ unless role || shard
177
153
  raise ArgumentError, "must provide a `shard` and/or `role`."
178
154
  end
155
+
156
+ unless role
157
+ raise ArgumentError, "`connected_to` cannot accept a `shard` argument without a `role`."
158
+ end
159
+
160
+ with_role_and_shard(role, shard, prevent_writes, &blk)
179
161
  end
180
162
 
181
163
  # Connects a role and/or shard to the provided connection names. Optionally +prevent_writes+
@@ -194,7 +176,7 @@ module ActiveRecord
194
176
  def connected_to_many(*classes, role:, shard: nil, prevent_writes: false)
195
177
  classes = classes.flatten
196
178
 
197
- if legacy_connection_handling
179
+ if ActiveRecord.legacy_connection_handling
198
180
  raise NotImplementedError, "connected_to_many is not available with legacy connection handling"
199
181
  end
200
182
 
@@ -202,7 +184,7 @@ module ActiveRecord
202
184
  raise NotImplementedError, "connected_to_many can only be called on ActiveRecord::Base."
203
185
  end
204
186
 
205
- prevent_writes = true if role == reading_role
187
+ prevent_writes = true if role == ActiveRecord.reading_role
206
188
 
207
189
  connected_to_stack << { role: role, shard: shard, prevent_writes: prevent_writes, klasses: classes }
208
190
  yield
@@ -218,11 +200,11 @@ module ActiveRecord
218
200
  # It is not recommended to use this method in a request since it
219
201
  # does not yield to a block like +connected_to+.
220
202
  def connecting_to(role: default_role, shard: default_shard, prevent_writes: false)
221
- if legacy_connection_handling
203
+ if ActiveRecord.legacy_connection_handling
222
204
  raise NotImplementedError, "`connecting_to` is not available with `legacy_connection_handling`."
223
205
  end
224
206
 
225
- prevent_writes = true if role == reading_role
207
+ prevent_writes = true if role == ActiveRecord.reading_role
226
208
 
227
209
  self.connected_to_stack << { role: role, shard: shard, prevent_writes: prevent_writes, klasses: [self] }
228
210
  end
@@ -239,7 +221,7 @@ module ActiveRecord
239
221
  # See +READ_QUERY+ for the queries that are blocked by this
240
222
  # method.
241
223
  def while_preventing_writes(enabled = true, &block)
242
- if legacy_connection_handling
224
+ if ActiveRecord.legacy_connection_handling
243
225
  connection_handler.while_preventing_writes(enabled, &block)
244
226
  else
245
227
  connected_to(role: current_role, prevent_writes: enabled, &block)
@@ -257,8 +239,8 @@ module ActiveRecord
257
239
  end
258
240
 
259
241
  def lookup_connection_handler(handler_key) # :nodoc:
260
- if ActiveRecord::Base.legacy_connection_handling
261
- handler_key ||= ActiveRecord::Base.writing_role
242
+ if ActiveRecord.legacy_connection_handling
243
+ handler_key ||= ActiveRecord.writing_role
262
244
  connection_handlers[handler_key] ||= ActiveRecord::ConnectionAdapters::ConnectionHandler.new
263
245
  else
264
246
  ActiveRecord::Base.connection_handler
@@ -267,7 +249,7 @@ module ActiveRecord
267
249
 
268
250
  # Clears the query cache for all connections associated with the current thread.
269
251
  def clear_query_caches_for_current_thread
270
- if ActiveRecord::Base.legacy_connection_handling
252
+ if ActiveRecord.legacy_connection_handling
271
253
  ActiveRecord::Base.connection_handlers.each_value do |handler|
272
254
  clear_on_handler(handler)
273
255
  end
@@ -294,7 +276,7 @@ module ActiveRecord
294
276
  end
295
277
 
296
278
  def primary_class? # :nodoc:
297
- self == Base || defined?(ApplicationRecord) && self == ApplicationRecord
279
+ self == Base || application_record_class?
298
280
  end
299
281
 
300
282
  # Returns the configuration of the associated connection as a hash:
@@ -374,9 +356,9 @@ module ActiveRecord
374
356
  end
375
357
 
376
358
  def with_role_and_shard(role, shard, prevent_writes)
377
- prevent_writes = true if role == reading_role
359
+ prevent_writes = true if role == ActiveRecord.reading_role
378
360
 
379
- if ActiveRecord::Base.legacy_connection_handling
361
+ if ActiveRecord.legacy_connection_handling
380
362
  with_handler(role.to_sym) do
381
363
  connection_handler.while_preventing_writes(prevent_writes) do
382
364
  self.connected_to_stack << { shard: shard, klasses: [self] }
@@ -17,20 +17,7 @@ module ActiveRecord
17
17
  # Accepts a logger conforming to the interface of Log4r which is then
18
18
  # passed on to any new database connections made and which can be
19
19
  # retrieved on both a class and instance level by calling +logger+.
20
- mattr_accessor :logger, instance_writer: false
21
-
22
- ##
23
- # :singleton-method:
24
- #
25
- # Specifies if the methods calling database queries should be logged below
26
- # their relevant queries. Defaults to false.
27
- mattr_accessor :verbose_query_logs, instance_writer: false, default: false
28
-
29
- ##
30
- # :singleton-method:
31
- #
32
- # Specifies the names of the queues used by background jobs.
33
- mattr_accessor :queues, instance_accessor: false, default: {}
20
+ class_attribute :logger, instance_writer: false
34
21
 
35
22
  ##
36
23
  # :singleton-method:
@@ -72,80 +59,17 @@ module ActiveRecord
72
59
 
73
60
  ##
74
61
  # :singleton-method:
75
- # Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling
76
- # dates and times from the database. This is set to :utc by default.
77
- mattr_accessor :default_timezone, instance_writer: false, default: :utc
78
-
79
- ##
80
- # :singleton-method:
81
- # Specifies the format to use when dumping the database schema with Rails'
82
- # Rakefile. If :sql, the schema is dumped as (potentially database-
83
- # specific) SQL statements. If :ruby, the schema is dumped as an
84
- # ActiveRecord::Schema file which can be loaded into any database that
85
- # supports migrations. Use :ruby if you want to have different database
86
- # adapters for, e.g., your development and test environments.
87
- mattr_accessor :schema_format, instance_writer: false, default: :ruby
88
-
89
- ##
90
- # :singleton-method:
91
- # Specifies if an error should be raised if the query has an order being
92
- # ignored when doing batch queries. Useful in applications where the
93
- # scope being ignored is error-worthy, rather than a warning.
94
- mattr_accessor :error_on_ignored_order, instance_writer: false, default: false
95
-
96
- ##
97
- # :singleton-method:
98
- # Specify whether or not to use timestamps for migration versions
99
- mattr_accessor :timestamped_migrations, instance_writer: false, default: true
100
-
101
- ##
102
- # :singleton-method:
103
- # Specify whether schema dump should happen at the end of the
104
- # db:migrate rails command. This is true by default, which is useful for the
105
- # development environment. This should ideally be false in the production
106
- # environment where dumping schema is rarely needed.
107
- mattr_accessor :dump_schema_after_migration, instance_writer: false, default: true
108
-
109
- ##
110
- # :singleton-method:
111
- # Specifies which database schemas to dump when calling db:schema:dump.
112
- # If the value is :schema_search_path (the default), any schemas listed in
113
- # schema_search_path are dumped. Use :all to dump all schemas regardless
114
- # of schema_search_path, or a string of comma separated schemas for a
115
- # custom list.
116
- mattr_accessor :dump_schemas, instance_writer: false, default: :schema_search_path
117
-
118
- ##
119
- # :singleton-method:
120
- # Specify a threshold for the size of query result sets. If the number of
121
- # records in the set exceeds the threshold, a warning is logged. This can
122
- # be used to identify queries which load thousands of records and
123
- # potentially cause memory bloat.
124
- mattr_accessor :warn_on_records_fetched_greater_than, instance_writer: false
125
-
126
- ##
127
- # :singleton-method:
128
- # Show a warning when Rails couldn't parse your database.yml
129
- # for multiple databases.
130
- mattr_accessor :suppress_multiple_database_warning, instance_writer: false, default: false
131
-
132
- mattr_accessor :maintain_test_schema, instance_accessor: false
62
+ # Force enumeration of all columns in SELECT statements.
63
+ # e.g. `SELECT first_name, last_name FROM ...` instead of `SELECT * FROM ...`
64
+ # This avoids +PreparedStatementCacheExpired+ errors when a column is added
65
+ # to the database while the app is running.
66
+ class_attribute :enumerate_columns_in_select_statements, instance_accessor: false, default: false
133
67
 
134
68
  class_attribute :belongs_to_required_by_default, instance_accessor: false
135
69
 
136
- ##
137
- # :singleton-method:
138
- # Set the application to log or raise when an association violates strict loading.
139
- # Defaults to :raise.
140
- mattr_accessor :action_on_strict_loading_violation, instance_accessor: false, default: :raise
141
-
142
70
  class_attribute :strict_loading_by_default, instance_accessor: false, default: false
143
71
 
144
- mattr_accessor :writing_role, instance_accessor: false, default: :writing
145
-
146
- mattr_accessor :reading_role, instance_accessor: false, default: :reading
147
-
148
- mattr_accessor :has_many_inversing, instance_accessor: false, default: false
72
+ class_attribute :has_many_inversing, instance_accessor: false, default: false
149
73
 
150
74
  class_attribute :default_connection_handler, instance_writer: false
151
75
 
@@ -153,7 +77,15 @@ module ActiveRecord
153
77
 
154
78
  class_attribute :default_shard, instance_writer: false
155
79
 
156
- mattr_accessor :legacy_connection_handling, instance_writer: false, default: true
80
+ def self.application_record_class? # :nodoc:
81
+ if ActiveRecord.application_record_class
82
+ self == ActiveRecord.application_record_class
83
+ else
84
+ if defined?(ApplicationRecord) && self == ApplicationRecord
85
+ true
86
+ end
87
+ end
88
+ end
157
89
 
158
90
  self.filter_attributes = []
159
91
 
@@ -166,7 +98,8 @@ module ActiveRecord
166
98
  end
167
99
 
168
100
  def self.connection_handlers
169
- unless legacy_connection_handling
101
+ if ActiveRecord.legacy_connection_handling
102
+ else
170
103
  raise NotImplementedError, "The new connection handling does not support accessing multiple connection handlers."
171
104
  end
172
105
 
@@ -174,13 +107,32 @@ module ActiveRecord
174
107
  end
175
108
 
176
109
  def self.connection_handlers=(handlers)
177
- unless legacy_connection_handling
178
- raise NotImplementedError, "The new connection handling does not setting support multiple connection handlers."
110
+ if ActiveRecord.legacy_connection_handling
111
+ ActiveSupport::Deprecation.warn(<<~MSG)
112
+ Using legacy connection handling is deprecated. Please set
113
+ `legacy_connection_handling` to `false` in your application.
114
+
115
+ The new connection handling does not support `connection_handlers`
116
+ getter and setter.
117
+
118
+ Read more about how to migrate at: https://guides.rubyonrails.org/active_record_multiple_databases.html#migrate-to-the-new-connection-handling
119
+ MSG
120
+ else
121
+ raise NotImplementedError, "The new connection handling does not support multiple connection handlers."
179
122
  end
180
123
 
181
124
  @@connection_handlers = handlers
182
125
  end
183
126
 
127
+ def self.asynchronous_queries_session # :nodoc:
128
+ asynchronous_queries_tracker.current_session
129
+ end
130
+
131
+ def self.asynchronous_queries_tracker # :nodoc:
132
+ Thread.current.thread_variable_get(:ar_asynchronous_queries_tracker) ||
133
+ Thread.current.thread_variable_set(:ar_asynchronous_queries_tracker, AsynchronousQueriesTracker.new)
134
+ end
135
+
184
136
  # Returns the symbol representing the current connected role.
185
137
  #
186
138
  # ActiveRecord::Base.connected_to(role: :writing) do
@@ -191,7 +143,7 @@ module ActiveRecord
191
143
  # ActiveRecord::Base.current_role #=> :reading
192
144
  # end
193
145
  def self.current_role
194
- if ActiveRecord::Base.legacy_connection_handling
146
+ if ActiveRecord.legacy_connection_handling
195
147
  connection_handlers.key(connection_handler) || default_role
196
148
  else
197
149
  connected_to_stack.reverse_each do |hash|
@@ -232,7 +184,7 @@ module ActiveRecord
232
184
  # ActiveRecord::Base.current_preventing_writes #=> false
233
185
  # end
234
186
  def self.current_preventing_writes
235
- if legacy_connection_handling
187
+ if ActiveRecord.legacy_connection_handling
236
188
  connection_handler.prevent_writes
237
189
  else
238
190
  connected_to_stack.reverse_each do |hash|
@@ -258,7 +210,7 @@ module ActiveRecord
258
210
  @connection_class = b
259
211
  end
260
212
 
261
- def self.connection_class # :nodoc
213
+ def self.connection_class # :nodoc:
262
214
  @connection_class ||= false
263
215
  end
264
216
 
@@ -278,19 +230,19 @@ module ActiveRecord
278
230
  end
279
231
 
280
232
  def self.allow_unsafe_raw_sql # :nodoc:
281
- ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_unsafe_raw_sql is deprecated and will be removed in Rails 6.2")
233
+ ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_unsafe_raw_sql is deprecated and will be removed in Rails 7.0")
282
234
  end
283
235
 
284
236
  def self.allow_unsafe_raw_sql=(value) # :nodoc:
285
- ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_unsafe_raw_sql= is deprecated and will be removed in Rails 6.2")
237
+ ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_unsafe_raw_sql= is deprecated and will be removed in Rails 7.0")
286
238
  end
287
239
 
288
240
  self.default_connection_handler = ConnectionAdapters::ConnectionHandler.new
289
- self.default_role = writing_role
241
+ self.default_role = ActiveRecord.writing_role
290
242
  self.default_shard = :default
291
243
 
292
244
  def self.strict_loading_violation!(owner:, reflection:) # :nodoc:
293
- case action_on_strict_loading_violation
245
+ case ActiveRecord.action_on_strict_loading_violation
294
246
  when :raise
295
247
  message = "`#{owner}` is marked for strict_loading. The `#{reflection.klass}` association named `:#{reflection.name}` cannot be lazily loaded."
296
248
  raise ActiveRecord::StrictLoadingViolationError.new(message)
@@ -381,7 +333,32 @@ module ActiveRecord
381
333
  end
382
334
 
383
335
  def find_by!(*args) # :nodoc:
384
- find_by(*args) || raise(RecordNotFound.new("Couldn't find #{name}", name))
336
+ find_by(*args) || where(*args).raise_record_not_found_exception!
337
+ end
338
+
339
+ %w(
340
+ reading_role writing_role legacy_connection_handling default_timezone index_nested_attribute_errors
341
+ verbose_query_logs queues warn_on_records_fetched_greater_than maintain_test_schema
342
+ application_record_class action_on_strict_loading_violation schema_format error_on_ignored_order
343
+ timestamped_migrations dump_schema_after_migration dump_schemas suppress_multiple_database_warning
344
+ ).each do |attr|
345
+ module_eval(<<~RUBY, __FILE__, __LINE__ + 1)
346
+ def #{attr}
347
+ ActiveSupport::Deprecation.warn(<<~MSG)
348
+ ActiveRecord::Base.#{attr} is deprecated and will be removed in Rails 7.1.
349
+ Use `ActiveRecord.#{attr}` instead.
350
+ MSG
351
+ ActiveRecord.#{attr}
352
+ end
353
+
354
+ def #{attr}=(value)
355
+ ActiveSupport::Deprecation.warn(<<~MSG)
356
+ ActiveRecord::Base.#{attr}= is deprecated and will be removed in Rails 7.1.
357
+ Use `ActiveRecord.#{attr}=` instead.
358
+ MSG
359
+ ActiveRecord.#{attr} = value
360
+ end
361
+ RUBY
385
362
  end
386
363
 
387
364
  def initialize_generated_modules # :nodoc:
@@ -408,7 +385,21 @@ module ActiveRecord
408
385
  end
409
386
 
410
387
  # Specifies columns which shouldn't be exposed while calling +#inspect+.
411
- attr_writer :filter_attributes
388
+ def filter_attributes=(filter_attributes)
389
+ @inspection_filter = nil
390
+ @filter_attributes = filter_attributes
391
+ end
392
+
393
+ def inspection_filter # :nodoc:
394
+ if defined?(@filter_attributes)
395
+ @inspection_filter ||= begin
396
+ mask = InspectionMask.new(ActiveSupport::ParameterFilter::FILTERED)
397
+ ActiveSupport::ParameterFilter.new(@filter_attributes, mask: mask)
398
+ end
399
+ else
400
+ superclass.inspection_filter
401
+ end
402
+ end
412
403
 
413
404
  # Returns a string like 'Post(id:integer, title:string, body:text)'
414
405
  def inspect # :nodoc:
@@ -432,10 +423,6 @@ module ActiveRecord
432
423
  end
433
424
 
434
425
  # Returns an instance of <tt>Arel::Table</tt> loaded with the current table name.
435
- #
436
- # class Post < ActiveRecord::Base
437
- # scope :published_and_commented, -> { published.and(arel_table[:comments_count].gt(0)) }
438
- # end
439
426
  def arel_table # :nodoc:
440
427
  @arel_table ||= Arel::Table.new(table_name, klass: self)
441
428
  end
@@ -453,10 +440,6 @@ module ActiveRecord
453
440
  TypeCaster::Map.new(self)
454
441
  end
455
442
 
456
- def _internal? # :nodoc:
457
- false
458
- end
459
-
460
443
  def cached_find_by_statement(key, &block) # :nodoc:
461
444
  cache = @find_by_statement_cache[connection.prepared_statements]
462
445
  cache.compute_if_absent(key) { StatementCache.create(connection, &block) }
@@ -616,6 +599,8 @@ module ActiveRecord
616
599
  # Delegates to id in order to allow two records of the same type and id to work with something like:
617
600
  # [ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
618
601
  def hash
602
+ id = self.id
603
+
619
604
  if id
620
605
  self.class.hash ^ id.hash
621
606
  else
@@ -667,11 +652,37 @@ module ActiveRecord
667
652
  # if the record tries to lazily load an association.
668
653
  #
669
654
  # user = User.first
670
- # user.strict_loading!
671
- # user.comments.to_a
655
+ # user.strict_loading! # => true
656
+ # user.comments
672
657
  # => ActiveRecord::StrictLoadingViolationError
673
- def strict_loading!
674
- @strict_loading = true
658
+ #
659
+ # === Parameters:
660
+ #
661
+ # * value - Boolean specifying whether to enable or disable strict loading.
662
+ # * mode - Symbol specifying strict loading mode. Defaults to :all. Using
663
+ # :n_plus_one_only mode will only raise an error if an association
664
+ # that will lead to an n plus one query is lazily loaded.
665
+ #
666
+ # === Example:
667
+ #
668
+ # user = User.first
669
+ # user.strict_loading!(false) # => false
670
+ # user.comments
671
+ # => #<ActiveRecord::Associations::CollectionProxy>
672
+ def strict_loading!(value = true, mode: :all)
673
+ unless [:all, :n_plus_one_only].include?(mode)
674
+ raise ArgumentError, "The :mode option must be one of [:all, :n_plus_one_only]."
675
+ end
676
+
677
+ @strict_loading_mode = mode
678
+ @strict_loading = value
679
+ end
680
+
681
+ attr_reader :strict_loading_mode
682
+
683
+ # Returns +true+ if the record uses strict_loading with +:n_plus_one_only+ mode enabled.
684
+ def strict_loading_n_plus_one_only?
685
+ @strict_loading_mode == :n_plus_one_only
675
686
  end
676
687
 
677
688
  # Marks this record as read only.
@@ -688,11 +699,11 @@ module ActiveRecord
688
699
  # We check defined?(@attributes) not to issue warnings if the object is
689
700
  # allocated but not initialized.
690
701
  inspection = if defined?(@attributes) && @attributes
691
- self.class.attribute_names.collect do |name|
702
+ self.class.attribute_names.filter_map do |name|
692
703
  if _has_attribute?(name)
693
704
  "#{name}: #{attribute_for_inspect(name)}"
694
705
  end
695
- end.compact.join(", ")
706
+ end.join(", ")
696
707
  else
697
708
  "not initialized"
698
709
  end
@@ -749,16 +760,20 @@ module ActiveRecord
749
760
  end
750
761
 
751
762
  def init_internals
752
- @primary_key = self.class.primary_key
753
763
  @readonly = false
754
764
  @previously_new_record = false
755
765
  @destroyed = false
756
766
  @marked_for_destruction = false
757
767
  @destroyed_by_association = nil
758
768
  @_start_transaction_state = nil
759
- @strict_loading = self.class.strict_loading_by_default
760
769
 
761
- self.class.define_attribute_methods
770
+ klass = self.class
771
+
772
+ @primary_key = klass.primary_key
773
+ @strict_loading = klass.strict_loading_by_default
774
+ @strict_loading_mode = :all
775
+
776
+ klass.define_attribute_methods
762
777
  end
763
778
 
764
779
  def initialize_internals_callback
@@ -776,10 +791,7 @@ module ActiveRecord
776
791
  private_constant :InspectionMask
777
792
 
778
793
  def inspection_filter
779
- @inspection_filter ||= begin
780
- mask = InspectionMask.new(ActiveSupport::ParameterFilter::FILTERED)
781
- ActiveSupport::ParameterFilter.new(self.class.filter_attributes, mask: mask)
782
- end
794
+ self.class.inspection_filter
783
795
  end
784
796
  end
785
797
  end