activerecord 6.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +726 -1329
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/active_record/aggregations.rb +1 -1
- data/lib/active_record/association_relation.rb +0 -10
- data/lib/active_record/associations/association.rb +31 -9
- data/lib/active_record/associations/association_scope.rb +1 -3
- data/lib/active_record/associations/belongs_to_association.rb +15 -4
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
- data/lib/active_record/associations/builder/association.rb +8 -2
- data/lib/active_record/associations/builder/belongs_to.rb +19 -6
- data/lib/active_record/associations/builder/collection_association.rb +1 -1
- data/lib/active_record/associations/builder/has_many.rb +3 -2
- data/lib/active_record/associations/builder/has_one.rb +2 -1
- data/lib/active_record/associations/builder/singular_association.rb +2 -2
- data/lib/active_record/associations/collection_association.rb +14 -23
- data/lib/active_record/associations/collection_proxy.rb +8 -3
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +2 -1
- data/lib/active_record/associations/has_one_association.rb +10 -7
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/preloader/association.rb +161 -47
- data/lib/active_record/associations/preloader/batch.rb +51 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +37 -11
- data/lib/active_record/associations/preloader.rb +46 -110
- data/lib/active_record/associations/singular_association.rb +8 -2
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +76 -81
- data/lib/active_record/asynchronous_queries_tracker.rb +57 -0
- data/lib/active_record/attribute_assignment.rb +1 -1
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
- data/lib/active_record/attribute_methods/dirty.rb +41 -16
- data/lib/active_record/attribute_methods/primary_key.rb +2 -2
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +7 -5
- data/lib/active_record/attribute_methods/serialization.rb +66 -12
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
- data/lib/active_record/attribute_methods/write.rb +7 -10
- data/lib/active_record/attribute_methods.rb +6 -9
- data/lib/active_record/attributes.rb +24 -35
- data/lib/active_record/autosave_association.rb +3 -18
- data/lib/active_record/base.rb +19 -1
- data/lib/active_record/callbacks.rb +2 -2
- data/lib/active_record/coders/yaml_column.rb +2 -14
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +312 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +31 -558
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +45 -21
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -12
- data/lib/active_record/connection_adapters/abstract/quoting.rb +11 -4
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -17
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -13
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +60 -16
- data/lib/active_record/connection_adapters/abstract/transaction.rb +3 -3
- data/lib/active_record/connection_adapters/abstract_adapter.rb +112 -66
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +96 -81
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +33 -23
- data/lib/active_record/connection_adapters/mysql/quoting.rb +16 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +1 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -6
- data/lib/active_record/connection_adapters/pool_config.rb +1 -3
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +19 -14
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +6 -6
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +32 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +12 -12
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +159 -102
- data/lib/active_record/connection_adapters/schema_cache.rb +36 -37
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +23 -19
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +4 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -30
- data/lib/active_record/connection_adapters.rb +6 -5
- data/lib/active_record/connection_handling.rb +20 -38
- data/lib/active_record/core.rb +111 -118
- data/lib/active_record/database_configurations/connection_url_resolver.rb +0 -1
- data/lib/active_record/database_configurations/database_config.rb +12 -0
- data/lib/active_record/database_configurations/hash_config.rb +27 -1
- data/lib/active_record/database_configurations/url_config.rb +2 -2
- data/lib/active_record/database_configurations.rb +17 -9
- data/lib/active_record/delegated_type.rb +33 -11
- data/lib/active_record/destroy_association_async_job.rb +1 -1
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +1 -1
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +44 -0
- data/lib/active_record/encryption/configurable.rb +61 -0
- data/lib/active_record/encryption/context.rb +35 -0
- data/lib/active_record/encryption/contexts.rb +72 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +208 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +155 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +29 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +42 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_serializer.rb +80 -0
- data/lib/active_record/encryption/null_encryptor.rb +21 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
- data/lib/active_record/encryption/scheme.rb +99 -0
- data/lib/active_record/encryption.rb +55 -0
- data/lib/active_record/enum.rb +41 -41
- data/lib/active_record/errors.rb +66 -3
- data/lib/active_record/fixture_set/file.rb +15 -1
- data/lib/active_record/fixture_set/table_row.rb +40 -5
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +16 -11
- data/lib/active_record/future_result.rb +139 -0
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +55 -17
- data/lib/active_record/insert_all.rb +34 -5
- data/lib/active_record/integration.rb +1 -1
- data/lib/active_record/internal_metadata.rb +1 -5
- data/lib/active_record/locking/optimistic.rb +10 -9
- data/lib/active_record/log_subscriber.rb +6 -2
- data/lib/active_record/middleware/database_selector/resolver.rb +6 -10
- data/lib/active_record/middleware/database_selector.rb +8 -3
- data/lib/active_record/migration/command_recorder.rb +4 -4
- data/lib/active_record/migration/compatibility.rb +89 -10
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration.rb +109 -79
- data/lib/active_record/model_schema.rb +45 -31
- data/lib/active_record/nested_attributes.rb +3 -3
- data/lib/active_record/no_touching.rb +2 -2
- data/lib/active_record/null_relation.rb +2 -6
- data/lib/active_record/persistence.rb +134 -45
- data/lib/active_record/query_cache.rb +2 -2
- data/lib/active_record/query_logs.rb +203 -0
- data/lib/active_record/querying.rb +15 -5
- data/lib/active_record/railtie.rb +117 -17
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +72 -48
- data/lib/active_record/readonly_attributes.rb +11 -0
- data/lib/active_record/reflection.rb +45 -44
- data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
- data/lib/active_record/relation/batches.rb +3 -3
- data/lib/active_record/relation/calculations.rb +39 -26
- data/lib/active_record/relation/delegation.rb +6 -6
- data/lib/active_record/relation/finder_methods.rb +31 -22
- data/lib/active_record/relation/merger.rb +20 -13
- data/lib/active_record/relation/predicate_builder.rb +1 -6
- data/lib/active_record/relation/query_attribute.rb +5 -11
- data/lib/active_record/relation/query_methods.rb +230 -47
- data/lib/active_record/relation/record_fetch_warning.rb +2 -2
- data/lib/active_record/relation/spawn_methods.rb +2 -2
- data/lib/active_record/relation/where_clause.rb +8 -4
- data/lib/active_record/relation.rb +166 -77
- data/lib/active_record/result.rb +17 -2
- data/lib/active_record/runtime_registry.rb +2 -4
- data/lib/active_record/sanitization.rb +11 -7
- data/lib/active_record/schema_dumper.rb +3 -3
- data/lib/active_record/schema_migration.rb +0 -4
- data/lib/active_record/scoping/default.rb +61 -12
- data/lib/active_record/scoping/named.rb +3 -11
- data/lib/active_record/scoping.rb +40 -22
- data/lib/active_record/serialization.rb +1 -1
- data/lib/active_record/signed_id.rb +1 -1
- data/lib/active_record/store.rb +1 -6
- data/lib/active_record/tasks/database_tasks.rb +106 -22
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -11
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +9 -13
- data/lib/active_record/timestamp.rb +3 -4
- data/lib/active_record/transactions.rb +9 -14
- data/lib/active_record/translation.rb +2 -2
- data/lib/active_record/type/adapter_specific_registry.rb +32 -7
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +2 -2
- data/lib/active_record/type/serialized.rb +1 -1
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record.rb +170 -2
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/crud.rb +18 -22
- data/lib/arel/delete_manager.rb +2 -4
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/delete_statement.rb +8 -13
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/update_statement.rb +3 -2
- data/lib/arel/predications.rb +1 -1
- data/lib/arel/select_manager.rb +10 -4
- data/lib/arel/table.rb +0 -1
- data/lib/arel/tree_manager.rb +0 -12
- data/lib/arel/update_manager.rb +2 -4
- data/lib/arel/visitors/dot.rb +80 -90
- data/lib/arel/visitors/mysql.rb +6 -1
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +43 -2
- data/lib/arel.rb +1 -1
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- metadata +55 -17
data/lib/active_record/core.rb
CHANGED
@@ -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
|
-
|
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
|
-
#
|
76
|
-
#
|
77
|
-
|
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
|
-
|
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,15 +77,15 @@ module ActiveRecord
|
|
153
77
|
|
154
78
|
class_attribute :default_shard, instance_writer: false
|
155
79
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
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
|
165
89
|
|
166
90
|
self.filter_attributes = []
|
167
91
|
|
@@ -174,7 +98,8 @@ module ActiveRecord
|
|
174
98
|
end
|
175
99
|
|
176
100
|
def self.connection_handlers
|
177
|
-
|
101
|
+
if ActiveRecord.legacy_connection_handling
|
102
|
+
else
|
178
103
|
raise NotImplementedError, "The new connection handling does not support accessing multiple connection handlers."
|
179
104
|
end
|
180
105
|
|
@@ -182,13 +107,32 @@ module ActiveRecord
|
|
182
107
|
end
|
183
108
|
|
184
109
|
def self.connection_handlers=(handlers)
|
185
|
-
|
186
|
-
|
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."
|
187
122
|
end
|
188
123
|
|
189
124
|
@@connection_handlers = handlers
|
190
125
|
end
|
191
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
|
+
|
192
136
|
# Returns the symbol representing the current connected role.
|
193
137
|
#
|
194
138
|
# ActiveRecord::Base.connected_to(role: :writing) do
|
@@ -199,7 +143,7 @@ module ActiveRecord
|
|
199
143
|
# ActiveRecord::Base.current_role #=> :reading
|
200
144
|
# end
|
201
145
|
def self.current_role
|
202
|
-
if ActiveRecord
|
146
|
+
if ActiveRecord.legacy_connection_handling
|
203
147
|
connection_handlers.key(connection_handler) || default_role
|
204
148
|
else
|
205
149
|
connected_to_stack.reverse_each do |hash|
|
@@ -240,7 +184,7 @@ module ActiveRecord
|
|
240
184
|
# ActiveRecord::Base.current_preventing_writes #=> false
|
241
185
|
# end
|
242
186
|
def self.current_preventing_writes
|
243
|
-
if legacy_connection_handling
|
187
|
+
if ActiveRecord.legacy_connection_handling
|
244
188
|
connection_handler.prevent_writes
|
245
189
|
else
|
246
190
|
connected_to_stack.reverse_each do |hash|
|
@@ -266,7 +210,7 @@ module ActiveRecord
|
|
266
210
|
@connection_class = b
|
267
211
|
end
|
268
212
|
|
269
|
-
def self.connection_class # :nodoc
|
213
|
+
def self.connection_class # :nodoc:
|
270
214
|
@connection_class ||= false
|
271
215
|
end
|
272
216
|
|
@@ -294,11 +238,11 @@ module ActiveRecord
|
|
294
238
|
end
|
295
239
|
|
296
240
|
self.default_connection_handler = ConnectionAdapters::ConnectionHandler.new
|
297
|
-
self.default_role = writing_role
|
241
|
+
self.default_role = ActiveRecord.writing_role
|
298
242
|
self.default_shard = :default
|
299
243
|
|
300
244
|
def self.strict_loading_violation!(owner:, reflection:) # :nodoc:
|
301
|
-
case action_on_strict_loading_violation
|
245
|
+
case ActiveRecord.action_on_strict_loading_violation
|
302
246
|
when :raise
|
303
247
|
message = "`#{owner}` is marked for strict_loading. The `#{reflection.klass}` association named `:#{reflection.name}` cannot be lazily loaded."
|
304
248
|
raise ActiveRecord::StrictLoadingViolationError.new(message)
|
@@ -389,7 +333,32 @@ module ActiveRecord
|
|
389
333
|
end
|
390
334
|
|
391
335
|
def find_by!(*args) # :nodoc:
|
392
|
-
find_by(*args) ||
|
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
|
393
362
|
end
|
394
363
|
|
395
364
|
def initialize_generated_modules # :nodoc:
|
@@ -454,10 +423,6 @@ module ActiveRecord
|
|
454
423
|
end
|
455
424
|
|
456
425
|
# Returns an instance of <tt>Arel::Table</tt> loaded with the current table name.
|
457
|
-
#
|
458
|
-
# class Post < ActiveRecord::Base
|
459
|
-
# scope :published_and_commented, -> { published.and(arel_table[:comments_count].gt(0)) }
|
460
|
-
# end
|
461
426
|
def arel_table # :nodoc:
|
462
427
|
@arel_table ||= Arel::Table.new(table_name, klass: self)
|
463
428
|
end
|
@@ -475,10 +440,6 @@ module ActiveRecord
|
|
475
440
|
TypeCaster::Map.new(self)
|
476
441
|
end
|
477
442
|
|
478
|
-
def _internal? # :nodoc:
|
479
|
-
false
|
480
|
-
end
|
481
|
-
|
482
443
|
def cached_find_by_statement(key, &block) # :nodoc:
|
483
444
|
cache = @find_by_statement_cache[connection.prepared_statements]
|
484
445
|
cache.compute_if_absent(key) { StatementCache.create(connection, &block) }
|
@@ -638,6 +599,8 @@ module ActiveRecord
|
|
638
599
|
# Delegates to id in order to allow two records of the same type and id to work with something like:
|
639
600
|
# [ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
|
640
601
|
def hash
|
602
|
+
id = self.id
|
603
|
+
|
641
604
|
if id
|
642
605
|
self.class.hash ^ id.hash
|
643
606
|
else
|
@@ -689,11 +652,37 @@ module ActiveRecord
|
|
689
652
|
# if the record tries to lazily load an association.
|
690
653
|
#
|
691
654
|
# user = User.first
|
692
|
-
# user.strict_loading!
|
693
|
-
# user.comments
|
655
|
+
# user.strict_loading! # => true
|
656
|
+
# user.comments
|
694
657
|
# => ActiveRecord::StrictLoadingViolationError
|
695
|
-
|
696
|
-
|
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
|
697
686
|
end
|
698
687
|
|
699
688
|
# Marks this record as read only.
|
@@ -710,11 +699,11 @@ module ActiveRecord
|
|
710
699
|
# We check defined?(@attributes) not to issue warnings if the object is
|
711
700
|
# allocated but not initialized.
|
712
701
|
inspection = if defined?(@attributes) && @attributes
|
713
|
-
self.class.attribute_names.
|
702
|
+
self.class.attribute_names.filter_map do |name|
|
714
703
|
if _has_attribute?(name)
|
715
704
|
"#{name}: #{attribute_for_inspect(name)}"
|
716
705
|
end
|
717
|
-
end.
|
706
|
+
end.join(", ")
|
718
707
|
else
|
719
708
|
"not initialized"
|
720
709
|
end
|
@@ -771,16 +760,20 @@ module ActiveRecord
|
|
771
760
|
end
|
772
761
|
|
773
762
|
def init_internals
|
774
|
-
@primary_key = self.class.primary_key
|
775
763
|
@readonly = false
|
776
764
|
@previously_new_record = false
|
777
765
|
@destroyed = false
|
778
766
|
@marked_for_destruction = false
|
779
767
|
@destroyed_by_association = nil
|
780
768
|
@_start_transaction_state = nil
|
781
|
-
@strict_loading = self.class.strict_loading_by_default
|
782
769
|
|
783
|
-
self.class
|
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
|
784
777
|
end
|
785
778
|
|
786
779
|
def initialize_internals_callback
|
@@ -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
|
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,
|
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? ||
|
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>
|
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
|
-
|
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
|
58
|
+
unless include_hidden
|
51
59
|
configs = configs.select do |db_config|
|
52
|
-
|
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?
|
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
|
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(
|
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
|
-
#
|
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.
|
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}
|
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
|
9
|
+
queue_as { ActiveRecord.queues[:destroy] }
|
10
10
|
|
11
11
|
discard_on ActiveJob::DeserializationError
|
12
12
|
|