activerecord 6.1.7.7 → 7.0.0.alpha1

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 (220) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +726 -1389
  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 +31 -9
  8. data/lib/active_record/associations/association_scope.rb +1 -3
  9. data/lib/active_record/associations/belongs_to_association.rb +15 -4
  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 +14 -23
  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 -47
  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 +2 -14
  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 +12 -14
  55. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -17
  56. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -13
  57. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +60 -16
  58. data/lib/active_record/connection_adapters/abstract/transaction.rb +3 -3
  59. data/lib/active_record/connection_adapters/abstract_adapter.rb +112 -66
  60. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +96 -81
  61. data/lib/active_record/connection_adapters/mysql/database_statements.rb +33 -23
  62. data/lib/active_record/connection_adapters/mysql/quoting.rb +16 -1
  63. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +1 -1
  64. data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -6
  65. data/lib/active_record/connection_adapters/pool_config.rb +1 -3
  66. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +19 -14
  67. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
  68. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
  69. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
  70. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
  71. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  72. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +28 -0
  73. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  74. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  75. data/lib/active_record/connection_adapters/postgresql/quoting.rb +6 -32
  76. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +32 -0
  77. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +5 -1
  78. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +12 -12
  79. data/lib/active_record/connection_adapters/postgresql_adapter.rb +159 -102
  80. data/lib/active_record/connection_adapters/schema_cache.rb +36 -37
  81. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +23 -19
  82. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +4 -2
  83. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -30
  84. data/lib/active_record/connection_adapters.rb +6 -5
  85. data/lib/active_record/connection_handling.rb +20 -38
  86. data/lib/active_record/core.rb +111 -125
  87. data/lib/active_record/database_configurations/connection_url_resolver.rb +0 -1
  88. data/lib/active_record/database_configurations/database_config.rb +12 -0
  89. data/lib/active_record/database_configurations/hash_config.rb +27 -1
  90. data/lib/active_record/database_configurations/url_config.rb +2 -2
  91. data/lib/active_record/database_configurations.rb +17 -9
  92. data/lib/active_record/delegated_type.rb +33 -11
  93. data/lib/active_record/destroy_association_async_job.rb +1 -1
  94. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  95. data/lib/active_record/dynamic_matchers.rb +1 -1
  96. data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
  97. data/lib/active_record/encryption/cipher.rb +53 -0
  98. data/lib/active_record/encryption/config.rb +44 -0
  99. data/lib/active_record/encryption/configurable.rb +61 -0
  100. data/lib/active_record/encryption/context.rb +35 -0
  101. data/lib/active_record/encryption/contexts.rb +72 -0
  102. data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
  103. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  104. data/lib/active_record/encryption/encryptable_record.rb +208 -0
  105. data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
  106. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  107. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  108. data/lib/active_record/encryption/encryptor.rb +155 -0
  109. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  110. data/lib/active_record/encryption/errors.rb +15 -0
  111. data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
  112. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +29 -0
  113. data/lib/active_record/encryption/key.rb +28 -0
  114. data/lib/active_record/encryption/key_generator.rb +42 -0
  115. data/lib/active_record/encryption/key_provider.rb +46 -0
  116. data/lib/active_record/encryption/message.rb +33 -0
  117. data/lib/active_record/encryption/message_serializer.rb +80 -0
  118. data/lib/active_record/encryption/null_encryptor.rb +21 -0
  119. data/lib/active_record/encryption/properties.rb +76 -0
  120. data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
  121. data/lib/active_record/encryption/scheme.rb +99 -0
  122. data/lib/active_record/encryption.rb +55 -0
  123. data/lib/active_record/enum.rb +41 -41
  124. data/lib/active_record/errors.rb +66 -3
  125. data/lib/active_record/fixture_set/file.rb +15 -1
  126. data/lib/active_record/fixture_set/table_row.rb +40 -5
  127. data/lib/active_record/fixture_set/table_rows.rb +4 -4
  128. data/lib/active_record/fixtures.rb +16 -11
  129. data/lib/active_record/future_result.rb +139 -0
  130. data/lib/active_record/gem_version.rb +4 -4
  131. data/lib/active_record/inheritance.rb +55 -17
  132. data/lib/active_record/insert_all.rb +34 -5
  133. data/lib/active_record/integration.rb +1 -1
  134. data/lib/active_record/internal_metadata.rb +1 -5
  135. data/lib/active_record/locking/optimistic.rb +10 -9
  136. data/lib/active_record/log_subscriber.rb +6 -2
  137. data/lib/active_record/middleware/database_selector/resolver.rb +6 -10
  138. data/lib/active_record/middleware/database_selector.rb +8 -3
  139. data/lib/active_record/migration/command_recorder.rb +4 -4
  140. data/lib/active_record/migration/compatibility.rb +89 -10
  141. data/lib/active_record/migration/join_table.rb +1 -1
  142. data/lib/active_record/migration.rb +109 -79
  143. data/lib/active_record/model_schema.rb +45 -31
  144. data/lib/active_record/nested_attributes.rb +3 -3
  145. data/lib/active_record/no_touching.rb +2 -2
  146. data/lib/active_record/null_relation.rb +2 -6
  147. data/lib/active_record/persistence.rb +134 -45
  148. data/lib/active_record/query_cache.rb +2 -2
  149. data/lib/active_record/query_logs.rb +203 -0
  150. data/lib/active_record/querying.rb +15 -5
  151. data/lib/active_record/railtie.rb +117 -17
  152. data/lib/active_record/railties/controller_runtime.rb +1 -1
  153. data/lib/active_record/railties/databases.rake +72 -48
  154. data/lib/active_record/readonly_attributes.rb +11 -0
  155. data/lib/active_record/reflection.rb +45 -44
  156. data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
  157. data/lib/active_record/relation/batches.rb +3 -3
  158. data/lib/active_record/relation/calculations.rb +39 -26
  159. data/lib/active_record/relation/delegation.rb +6 -6
  160. data/lib/active_record/relation/finder_methods.rb +31 -22
  161. data/lib/active_record/relation/merger.rb +20 -13
  162. data/lib/active_record/relation/predicate_builder.rb +1 -6
  163. data/lib/active_record/relation/query_attribute.rb +5 -11
  164. data/lib/active_record/relation/query_methods.rb +230 -49
  165. data/lib/active_record/relation/record_fetch_warning.rb +2 -2
  166. data/lib/active_record/relation/spawn_methods.rb +2 -2
  167. data/lib/active_record/relation/where_clause.rb +8 -4
  168. data/lib/active_record/relation.rb +166 -77
  169. data/lib/active_record/result.rb +17 -2
  170. data/lib/active_record/runtime_registry.rb +2 -4
  171. data/lib/active_record/sanitization.rb +11 -7
  172. data/lib/active_record/schema_dumper.rb +3 -3
  173. data/lib/active_record/schema_migration.rb +0 -4
  174. data/lib/active_record/scoping/default.rb +61 -12
  175. data/lib/active_record/scoping/named.rb +3 -11
  176. data/lib/active_record/scoping.rb +40 -22
  177. data/lib/active_record/serialization.rb +1 -1
  178. data/lib/active_record/signed_id.rb +1 -1
  179. data/lib/active_record/store.rb +1 -6
  180. data/lib/active_record/tasks/database_tasks.rb +106 -22
  181. data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
  182. data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -11
  183. data/lib/active_record/test_databases.rb +1 -1
  184. data/lib/active_record/test_fixtures.rb +9 -13
  185. data/lib/active_record/timestamp.rb +3 -4
  186. data/lib/active_record/transactions.rb +9 -14
  187. data/lib/active_record/translation.rb +2 -2
  188. data/lib/active_record/type/adapter_specific_registry.rb +32 -7
  189. data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
  190. data/lib/active_record/type/internal/timezone.rb +2 -2
  191. data/lib/active_record/type/serialized.rb +1 -1
  192. data/lib/active_record/type/type_map.rb +17 -20
  193. data/lib/active_record/type.rb +1 -2
  194. data/lib/active_record/validations/associated.rb +1 -1
  195. data/lib/active_record.rb +170 -2
  196. data/lib/arel/attributes/attribute.rb +0 -8
  197. data/lib/arel/crud.rb +18 -22
  198. data/lib/arel/delete_manager.rb +2 -4
  199. data/lib/arel/insert_manager.rb +2 -3
  200. data/lib/arel/nodes/casted.rb +1 -1
  201. data/lib/arel/nodes/delete_statement.rb +8 -13
  202. data/lib/arel/nodes/insert_statement.rb +2 -2
  203. data/lib/arel/nodes/select_core.rb +2 -2
  204. data/lib/arel/nodes/select_statement.rb +2 -2
  205. data/lib/arel/nodes/update_statement.rb +3 -2
  206. data/lib/arel/predications.rb +1 -1
  207. data/lib/arel/select_manager.rb +10 -4
  208. data/lib/arel/table.rb +0 -1
  209. data/lib/arel/tree_manager.rb +0 -12
  210. data/lib/arel/update_manager.rb +2 -4
  211. data/lib/arel/visitors/dot.rb +80 -90
  212. data/lib/arel/visitors/mysql.rb +6 -1
  213. data/lib/arel/visitors/postgresql.rb +0 -10
  214. data/lib/arel/visitors/to_sql.rb +43 -2
  215. data/lib/arel.rb +1 -1
  216. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  217. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
  218. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  219. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  220. metadata +55 -17
@@ -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,22 +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
157
-
158
- # Application configurable boolean that instructs the YAML Coder to use
159
- # an unsafe load if set to true.
160
- mattr_accessor :use_yaml_unsafe_load, instance_writer: false, default: false
161
-
162
- # Application configurable array that provides additional permitted classes
163
- # to Psych safe_load in the YAML Coder
164
- mattr_accessor :yaml_column_permitted_classes, instance_writer: false, default: [Symbol]
165
-
166
- ##
167
- # :singleton-method:
168
- # Application configurable boolean that denotes whether or not to raise
169
- # an exception when the PostgreSQLAdapter is provided with an integer that is
170
- # wider than signed 64bit representation
171
- mattr_accessor :raise_int_wider_than_64bit, 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
172
89
 
173
90
  self.filter_attributes = []
174
91
 
@@ -181,7 +98,8 @@ module ActiveRecord
181
98
  end
182
99
 
183
100
  def self.connection_handlers
184
- unless legacy_connection_handling
101
+ if ActiveRecord.legacy_connection_handling
102
+ else
185
103
  raise NotImplementedError, "The new connection handling does not support accessing multiple connection handlers."
186
104
  end
187
105
 
@@ -189,13 +107,32 @@ module ActiveRecord
189
107
  end
190
108
 
191
109
  def self.connection_handlers=(handlers)
192
- unless legacy_connection_handling
193
- 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."
194
122
  end
195
123
 
196
124
  @@connection_handlers = handlers
197
125
  end
198
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
+
199
136
  # Returns the symbol representing the current connected role.
200
137
  #
201
138
  # ActiveRecord::Base.connected_to(role: :writing) do
@@ -206,7 +143,7 @@ module ActiveRecord
206
143
  # ActiveRecord::Base.current_role #=> :reading
207
144
  # end
208
145
  def self.current_role
209
- if ActiveRecord::Base.legacy_connection_handling
146
+ if ActiveRecord.legacy_connection_handling
210
147
  connection_handlers.key(connection_handler) || default_role
211
148
  else
212
149
  connected_to_stack.reverse_each do |hash|
@@ -247,7 +184,7 @@ module ActiveRecord
247
184
  # ActiveRecord::Base.current_preventing_writes #=> false
248
185
  # end
249
186
  def self.current_preventing_writes
250
- if legacy_connection_handling
187
+ if ActiveRecord.legacy_connection_handling
251
188
  connection_handler.prevent_writes
252
189
  else
253
190
  connected_to_stack.reverse_each do |hash|
@@ -273,7 +210,7 @@ module ActiveRecord
273
210
  @connection_class = b
274
211
  end
275
212
 
276
- def self.connection_class # :nodoc
213
+ def self.connection_class # :nodoc:
277
214
  @connection_class ||= false
278
215
  end
279
216
 
@@ -301,11 +238,11 @@ module ActiveRecord
301
238
  end
302
239
 
303
240
  self.default_connection_handler = ConnectionAdapters::ConnectionHandler.new
304
- self.default_role = writing_role
241
+ self.default_role = ActiveRecord.writing_role
305
242
  self.default_shard = :default
306
243
 
307
244
  def self.strict_loading_violation!(owner:, reflection:) # :nodoc:
308
- case action_on_strict_loading_violation
245
+ case ActiveRecord.action_on_strict_loading_violation
309
246
  when :raise
310
247
  message = "`#{owner}` is marked for strict_loading. The `#{reflection.klass}` association named `:#{reflection.name}` cannot be lazily loaded."
311
248
  raise ActiveRecord::StrictLoadingViolationError.new(message)
@@ -396,7 +333,32 @@ module ActiveRecord
396
333
  end
397
334
 
398
335
  def find_by!(*args) # :nodoc:
399
- 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
400
362
  end
401
363
 
402
364
  def initialize_generated_modules # :nodoc:
@@ -461,10 +423,6 @@ module ActiveRecord
461
423
  end
462
424
 
463
425
  # Returns an instance of <tt>Arel::Table</tt> loaded with the current table name.
464
- #
465
- # class Post < ActiveRecord::Base
466
- # scope :published_and_commented, -> { published.and(arel_table[:comments_count].gt(0)) }
467
- # end
468
426
  def arel_table # :nodoc:
469
427
  @arel_table ||= Arel::Table.new(table_name, klass: self)
470
428
  end
@@ -482,10 +440,6 @@ module ActiveRecord
482
440
  TypeCaster::Map.new(self)
483
441
  end
484
442
 
485
- def _internal? # :nodoc:
486
- false
487
- end
488
-
489
443
  def cached_find_by_statement(key, &block) # :nodoc:
490
444
  cache = @find_by_statement_cache[connection.prepared_statements]
491
445
  cache.compute_if_absent(key) { StatementCache.create(connection, &block) }
@@ -645,6 +599,8 @@ module ActiveRecord
645
599
  # Delegates to id in order to allow two records of the same type and id to work with something like:
646
600
  # [ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
647
601
  def hash
602
+ id = self.id
603
+
648
604
  if id
649
605
  self.class.hash ^ id.hash
650
606
  else
@@ -696,11 +652,37 @@ module ActiveRecord
696
652
  # if the record tries to lazily load an association.
697
653
  #
698
654
  # user = User.first
699
- # user.strict_loading!
700
- # user.comments.to_a
655
+ # user.strict_loading! # => true
656
+ # user.comments
701
657
  # => ActiveRecord::StrictLoadingViolationError
702
- def strict_loading!
703
- @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
704
686
  end
705
687
 
706
688
  # Marks this record as read only.
@@ -717,11 +699,11 @@ module ActiveRecord
717
699
  # We check defined?(@attributes) not to issue warnings if the object is
718
700
  # allocated but not initialized.
719
701
  inspection = if defined?(@attributes) && @attributes
720
- self.class.attribute_names.collect do |name|
702
+ self.class.attribute_names.filter_map do |name|
721
703
  if _has_attribute?(name)
722
704
  "#{name}: #{attribute_for_inspect(name)}"
723
705
  end
724
- end.compact.join(", ")
706
+ end.join(", ")
725
707
  else
726
708
  "not initialized"
727
709
  end
@@ -778,16 +760,20 @@ module ActiveRecord
778
760
  end
779
761
 
780
762
  def init_internals
781
- @primary_key = self.class.primary_key
782
763
  @readonly = false
783
764
  @previously_new_record = false
784
765
  @destroyed = false
785
766
  @marked_for_destruction = false
786
767
  @destroyed_by_association = nil
787
768
  @_start_transaction_state = nil
788
- @strict_loading = self.class.strict_loading_by_default
789
769
 
790
- 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
791
777
  end
792
778
 
793
779
  def initialize_internals_callback
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "uri"
4
3
  require "active_support/core_ext/enumerable"
5
4
 
6
5
  module ActiveRecord
@@ -48,6 +48,18 @@ module ActiveRecord
48
48
  raise NotImplementedError
49
49
  end
50
50
 
51
+ def min_threads
52
+ raise NotImplementedError
53
+ end
54
+
55
+ def max_threads
56
+ raise NotImplementedError
57
+ end
58
+
59
+ def max_queue
60
+ raise NotImplementedError
61
+ end
62
+
51
63
  def checkout_timeout
52
64
  raise NotImplementedError
53
65
  end
@@ -26,13 +26,14 @@ module ActiveRecord
26
26
  # connections.
27
27
  class HashConfig < DatabaseConfig
28
28
  attr_reader :configuration_hash
29
+
29
30
  def initialize(env_name, name, configuration_hash)
30
31
  super(env_name, name)
31
32
  @configuration_hash = configuration_hash.symbolize_keys.freeze
32
33
  end
33
34
 
34
35
  def config
35
- ActiveSupport::Deprecation.warn("DatabaseConfig#config will be removed in 7.0.0 in favor of DatabaseConfig#configuration_hash which returns a hash with symbol keys")
36
+ ActiveSupport::Deprecation.warn("DatabaseConfig#config will be removed in 7.0.0 in favor of DatabaseConfigurations#configuration_hash which returns a hash with symbol keys")
36
37
  configuration_hash.stringify_keys
37
38
  end
38
39
 
@@ -54,6 +55,10 @@ module ActiveRecord
54
55
  configuration_hash[:host]
55
56
  end
56
57
 
58
+ def socket # :nodoc:
59
+ configuration_hash[:socket]
60
+ end
61
+
57
62
  def database
58
63
  configuration_hash[:database]
59
64
  end
@@ -66,6 +71,18 @@ module ActiveRecord
66
71
  (configuration_hash[:pool] || 5).to_i
67
72
  end
68
73
 
74
+ def min_threads
75
+ (configuration_hash[:min_threads] || 0).to_i
76
+ end
77
+
78
+ def max_threads
79
+ (configuration_hash[:max_threads] || pool).to_i
80
+ end
81
+
82
+ def max_queue
83
+ max_threads * 4
84
+ end
85
+
69
86
  def checkout_timeout
70
87
  (configuration_hash[:checkout_timeout] || 5).to_f
71
88
  end
@@ -91,6 +108,15 @@ module ActiveRecord
91
108
  def schema_cache_path
92
109
  configuration_hash[:schema_cache_path]
93
110
  end
111
+
112
+ # Determines whether to dump the schema for a database.
113
+ def schema_dump
114
+ configuration_hash.fetch(:schema_dump, true)
115
+ end
116
+
117
+ def database_tasks? # :nodoc:
118
+ !replica? && !!configuration_hash.fetch(:database_tasks, true)
119
+ end
94
120
  end
95
121
  end
96
122
  end
@@ -19,7 +19,7 @@ module ActiveRecord
19
19
  #
20
20
  # ==== Options
21
21
  #
22
- # * <tt>:env_name</tt> - The Rails environment, ie "development".
22
+ # * <tt>:env_name</tt> - The Rails environment, i.e. "development".
23
23
  # * <tt>:name</tt> - The db config name. In a standard two-tier
24
24
  # database configuration this will default to "primary". In a multiple
25
25
  # database three-tier database configuration this corresponds to the name
@@ -42,7 +42,7 @@ module ActiveRecord
42
42
  # Return a Hash that can be merged into the main config that represents
43
43
  # the passed in url
44
44
  def build_url_hash
45
- if url.nil? || %w(jdbc: http: https:).any? { |protocol| url.start_with?(protocol) }
45
+ if url.nil? || url.start_with?("jdbc:", "http:", "https:")
46
46
  { url: url }
47
47
  else
48
48
  ConnectionUrlResolver.new(url).to_hash
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "uri"
4
3
  require "active_record/database_configurations/database_config"
5
4
  require "active_record/database_configurations/hash_config"
6
5
  require "active_record/database_configurations/url_config"
@@ -21,7 +20,7 @@ module ActiveRecord
21
20
  end
22
21
 
23
22
  # Collects the configs for the environment and optionally the specification
24
- # name passed in. To include replica configurations pass <tt>include_replicas: true</tt>.
23
+ # name passed in. To include replica configurations pass <tt>include_hidden: true</tt>.
25
24
  #
26
25
  # If a name is provided a single DatabaseConfig object will be
27
26
  # returned, otherwise an array of DatabaseConfig objects will be
@@ -34,22 +33,31 @@ module ActiveRecord
34
33
  # * <tt>name:</tt> The db config name (i.e. primary, animals, etc.). Defaults
35
34
  # to +nil+. If no +env_name+ is specified the config for the default env and the
36
35
  # passed +name+ will be returned.
37
- # * <tt>include_replicas:</tt> Determines whether to include replicas in
36
+ # * <tt>include_replicas:</tt> Deprecated. Determines whether to include replicas in
38
37
  # the returned list. Most of the time we're only iterating over the write
39
38
  # connection (i.e. migrations don't need to run for the write and read connection).
40
39
  # Defaults to +false+.
41
- def configs_for(env_name: nil, spec_name: nil, name: nil, include_replicas: false)
40
+ # * <tt>include_hidden:</tte Determines whether to include replicas and configurations
41
+ # hidden by +database_tasks: false+ in the returned list. Most of the time we're only
42
+ # iterating over the primary connections (i.e. migrations don't need to run for the
43
+ # write and read connection). Defaults to +false+.
44
+ def configs_for(env_name: nil, spec_name: nil, name: nil, include_replicas: false, include_hidden: false)
42
45
  if spec_name
43
46
  name = spec_name
44
47
  ActiveSupport::Deprecation.warn("The kwarg `spec_name` is deprecated in favor of `name`. `spec_name` will be removed in Rails 7.0")
45
48
  end
46
49
 
50
+ if include_replicas
51
+ include_hidden = include_replicas
52
+ ActiveSupport::Deprecation.warn("The kwarg `include_replicas` is deprecated in favor of `include_hidden`. When `include_hidden` is passed, configurations with `replica: true` or `database_tasks: false` will be returned. `include_replicas` will be removed in Rails 7.1.")
53
+ end
54
+
47
55
  env_name ||= default_env if name
48
56
  configs = env_with_configs(env_name)
49
57
 
50
- unless include_replicas
58
+ unless include_hidden
51
59
  configs = configs.select do |db_config|
52
- !db_config.replica?
60
+ db_config.database_tasks?
53
61
  end
54
62
  end
55
63
 
@@ -167,7 +175,7 @@ module ActiveRecord
167
175
  return configs if configs.is_a?(Array)
168
176
 
169
177
  db_configs = configs.flat_map do |env_name, config|
170
- if config.is_a?(Hash) && config.all? { |_, v| v.is_a?(Hash) }
178
+ if config.is_a?(Hash) && config.values.all?(Hash)
171
179
  walk_configs(env_name.to_s, config)
172
180
  else
173
181
  build_db_config_from_raw_config(env_name.to_s, "primary", config)
@@ -194,7 +202,7 @@ module ActiveRecord
194
202
  raise AdapterNotSpecified, <<~MSG
195
203
  The `#{name}` database is not configured for the `#{default_env}` environment.
196
204
 
197
- Available databases configurations are:
205
+ Available database configurations are:
198
206
 
199
207
  #{build_configuration_sentence}
200
208
  MSG
@@ -202,7 +210,7 @@ module ActiveRecord
202
210
  end
203
211
 
204
212
  def build_configuration_sentence
205
- configs = configs_for(include_replicas: true)
213
+ configs = configs_for(include_hidden: true)
206
214
 
207
215
  configs.group_by(&:env_name).map do |env, config|
208
216
  names = config.map(&:name)
@@ -51,10 +51,9 @@ module ActiveRecord
51
51
  # end
52
52
  # end
53
53
  #
54
- # # Schema: messages[ id, subject ]
54
+ # # Schema: messages[ id, subject, body ]
55
55
  # class Message < ApplicationRecord
56
56
  # include Entryable
57
- # has_rich_text :content
58
57
  # end
59
58
  #
60
59
  # # Schema: comments[ id, content ]
@@ -66,7 +65,7 @@ module ActiveRecord
66
65
  # resides in the +Entry+ "superclass". But the +Entry+ absolutely can stand alone in terms of querying capacity
67
66
  # in particular. You can now easily do things like:
68
67
  #
69
- # Account.entries.order(created_at: :desc).limit(50)
68
+ # Account.find(1).entries.order(created_at: :desc).limit(50)
70
69
  #
71
70
  # Which is exactly what you want when displaying both comments and messages together. The entry itself can
72
71
  # be rendered as its delegated type easily, like so:
@@ -76,7 +75,9 @@ module ActiveRecord
76
75
  #
77
76
  # # entries/entryables/_message.html.erb
78
77
  # <div class="message">
79
- # Posted on <%= entry.created_at %> by <%= entry.creator.name %>: <%= entry.message.content %>
78
+ # <div class="subject"><%= entry.message.subject %></div>
79
+ # <p><%= entry.message.body %></p>
80
+ # <i>Posted on <%= entry.created_at %> by <%= entry.creator.name %></i>
80
81
  # </div>
81
82
  #
82
83
  # # entries/entryables/_comment.html.erb
@@ -156,8 +157,6 @@ module ActiveRecord
156
157
  # Entry#comment # => returns the comment record, when entryable_type == "Comment", otherwise nil
157
158
  # Entry#comment_id # => returns entryable_id, when entryable_type == "Comment", otherwise nil
158
159
  #
159
- # The +options+ are passed directly to the +belongs_to+ call, so this is where you declare +dependent+ etc.
160
- #
161
160
  # You can also declare namespaced types:
162
161
  #
163
162
  # class Entry < ApplicationRecord
@@ -167,15 +166,38 @@ module ActiveRecord
167
166
  # Entry.access_notice_messages
168
167
  # entry.access_notice_message
169
168
  # entry.access_notice_message?
169
+ #
170
+ # === Options
171
+ #
172
+ # The +options+ are passed directly to the +belongs_to+ call, so this is where you declare +dependent+ etc.
173
+ # The following options can be included to specialize the behavior of the delegated type convenience methods.
174
+ #
175
+ # [:foreign_key]
176
+ # Specify the foreign key used for the convenience methods. By default this is guessed to be the passed
177
+ # +role+ with an "_id" suffix. So a class that defines a
178
+ # <tt>delegated_type :entryable, types: %w[ Message Comment ]</tt> association will use "entryable_id" as
179
+ # the default <tt>:foreign_key</tt>.
180
+ # [:primary_key]
181
+ # Specify the method that returns the primary key of associated object used for the convenience methods.
182
+ # By default this is +id+.
183
+ #
184
+ # Option examples:
185
+ # class Entry < ApplicationRecord
186
+ # delegated_type :entryable, types: %w[ Message Comment ], primary_key: :uuid, foreign_key: :entryable_uuid
187
+ # end
188
+ #
189
+ # Entry#message_uuid # => returns entryable_uuid, when entryable_type == "Message", otherwise nil
190
+ # Entry#comment_uuid # => returns entryable_uuid, when entryable_type == "Comment", otherwise nil
170
191
  def delegated_type(role, types:, **options)
171
192
  belongs_to role, options.delete(:scope), **options.merge(polymorphic: true)
172
- define_delegated_type_methods role, types: types
193
+ define_delegated_type_methods role, types: types, options: options
173
194
  end
174
195
 
175
196
  private
176
- def define_delegated_type_methods(role, types:)
197
+ def define_delegated_type_methods(role, types:, options:)
198
+ primary_key = options[:primary_key] || "id"
177
199
  role_type = "#{role}_type"
178
- role_id = "#{role}_id"
200
+ role_id = options[:foreign_key] || "#{role}_id"
179
201
 
180
202
  define_method "#{role}_class" do
181
203
  public_send("#{role}_type").constantize
@@ -186,7 +208,7 @@ module ActiveRecord
186
208
  end
187
209
 
188
210
  types.each do |type|
189
- scope_name = type.tableize.gsub("/", "_")
211
+ scope_name = type.tableize.tr("/", "_")
190
212
  singular = scope_name.singularize
191
213
  query = "#{singular}?"
192
214
 
@@ -200,7 +222,7 @@ module ActiveRecord
200
222
  public_send(role) if public_send(query)
201
223
  end
202
224
 
203
- define_method "#{singular}_id" do
225
+ define_method "#{singular}_#{primary_key}" do
204
226
  public_send(role_id) if public_send(query)
205
227
  end
206
228
  end
@@ -6,7 +6,7 @@ module ActiveRecord
6
6
 
7
7
  # Job to destroy the records associated with a destroyed record in background.
8
8
  class DestroyAssociationAsyncJob < ActiveJob::Base
9
- queue_as { ActiveRecord::Base.queues[:destroy] }
9
+ queue_as { ActiveRecord.queues[:destroy] }
10
10
 
11
11
  discard_on ActiveJob::DeserializationError
12
12