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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +734 -1058
- 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 +35 -7
- data/lib/active_record/associations/association_scope.rb +1 -3
- data/lib/active_record/associations/belongs_to_association.rb +16 -6
- 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 +24 -25
- 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 -49
- 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 +11 -1
- 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 +14 -7
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +5 -18
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -9
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +60 -16
- data/lib/active_record/connection_adapters/abstract/transaction.rb +17 -6
- data/lib/active_record/connection_adapters/abstract_adapter.rb +115 -69
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +96 -81
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +6 -2
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +33 -21
- data/lib/active_record/connection_adapters/mysql/quoting.rb +16 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +3 -0
- 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/pool_manager.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +19 -12
- 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 +157 -100
- data/lib/active_record/connection_adapters/schema_cache.rb +35 -4
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +0 -2
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +23 -17
- 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 +8 -5
- data/lib/active_record/connection_handling.rb +20 -38
- data/lib/active_record/core.rb +129 -117
- 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 +18 -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 +44 -46
- 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 +39 -6
- data/lib/active_record/integration.rb +1 -1
- data/lib/active_record/internal_metadata.rb +3 -5
- data/lib/active_record/legacy_yaml_adapter.rb +1 -1
- 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 +83 -1
- 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 +46 -32
- 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 +83 -58
- 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 +42 -25
- data/lib/active_record/relation/delegation.rb +6 -6
- data/lib/active_record/relation/finder_methods.rb +32 -23
- 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 +233 -50
- 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 +22 -15
- data/lib/active_record/relation.rb +170 -87
- 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 +62 -15
- 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/statement_cache.rb +2 -2
- data/lib/active_record/tasks/database_tasks.rb +107 -23
- 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 +45 -4
- 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/validations/numericality.rb +1 -1
- data/lib/active_record.rb +170 -2
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/collectors/bind.rb +2 -2
- data/lib/arel/collectors/composite.rb +3 -3
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- 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/homogeneous_in.rb +4 -0
- 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 +3 -3
- 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 +44 -3
- 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 -16
@@ -2,9 +2,11 @@
|
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Associations
|
5
|
-
class SingularAssociation < Association
|
5
|
+
class SingularAssociation < Association # :nodoc:
|
6
6
|
# Implements the reader method, e.g. foo.bar for Foo.has_one :bar
|
7
7
|
def reader
|
8
|
+
ensure_klass_exists!
|
9
|
+
|
8
10
|
if !loaded? || stale_target?
|
9
11
|
reload
|
10
12
|
end
|
@@ -36,7 +38,11 @@ module ActiveRecord
|
|
36
38
|
end
|
37
39
|
|
38
40
|
def find_target
|
39
|
-
|
41
|
+
if disable_joins
|
42
|
+
scope.first
|
43
|
+
else
|
44
|
+
super.first
|
45
|
+
end
|
40
46
|
end
|
41
47
|
|
42
48
|
def replace(record)
|
@@ -1,11 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/core_ext/enumerable"
|
4
|
-
require "active_support/core_ext/string/conversions"
|
5
|
-
|
6
3
|
module ActiveRecord
|
7
|
-
class AssociationNotFoundError < ConfigurationError
|
4
|
+
class AssociationNotFoundError < ConfigurationError # :nodoc:
|
8
5
|
attr_reader :record, :association_name
|
6
|
+
|
9
7
|
def initialize(record = nil, association_name = nil)
|
10
8
|
@record = record
|
11
9
|
@association_name = association_name
|
@@ -16,32 +14,25 @@ module ActiveRecord
|
|
16
14
|
end
|
17
15
|
end
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
@error = error
|
22
|
-
end
|
17
|
+
if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
|
18
|
+
include DidYouMean::Correctable
|
23
19
|
|
24
20
|
def corrections
|
25
|
-
if
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
}.reverse.first(4)
|
21
|
+
if record && association_name
|
22
|
+
@corrections ||= begin
|
23
|
+
maybe_these = record.class.reflections.keys
|
24
|
+
DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(association_name)
|
25
|
+
end
|
31
26
|
else
|
32
27
|
[]
|
33
28
|
end
|
34
29
|
end
|
35
30
|
end
|
36
|
-
|
37
|
-
# We may not have DYM, and DYM might not let us register error handlers
|
38
|
-
if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
|
39
|
-
DidYouMean.correct_error(self, Correction)
|
40
|
-
end
|
41
31
|
end
|
42
32
|
|
43
|
-
class InverseOfAssociationNotFoundError < ActiveRecordError
|
33
|
+
class InverseOfAssociationNotFoundError < ActiveRecordError # :nodoc:
|
44
34
|
attr_reader :reflection, :associated_class
|
35
|
+
|
45
36
|
def initialize(reflection = nil, associated_class = nil)
|
46
37
|
if reflection
|
47
38
|
@reflection = reflection
|
@@ -52,31 +43,23 @@ module ActiveRecord
|
|
52
43
|
end
|
53
44
|
end
|
54
45
|
|
55
|
-
|
56
|
-
|
57
|
-
@error = error
|
58
|
-
end
|
46
|
+
if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
|
47
|
+
include DidYouMean::Correctable
|
59
48
|
|
60
49
|
def corrections
|
61
|
-
if
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
}.reverse.first(4)
|
50
|
+
if reflection && associated_class
|
51
|
+
@corrections ||= begin
|
52
|
+
maybe_these = associated_class.reflections.keys
|
53
|
+
DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(reflection.options[:inverse_of].to_s)
|
54
|
+
end
|
67
55
|
else
|
68
56
|
[]
|
69
57
|
end
|
70
58
|
end
|
71
59
|
end
|
72
|
-
|
73
|
-
# We may not have DYM, and DYM might not let us register error handlers
|
74
|
-
if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
|
75
|
-
DidYouMean.correct_error(self, Correction)
|
76
|
-
end
|
77
60
|
end
|
78
61
|
|
79
|
-
class HasManyThroughAssociationNotFoundError < ActiveRecordError
|
62
|
+
class HasManyThroughAssociationNotFoundError < ActiveRecordError # :nodoc:
|
80
63
|
attr_reader :owner_class, :reflection
|
81
64
|
|
82
65
|
def initialize(owner_class = nil, reflection = nil)
|
@@ -89,32 +72,24 @@ module ActiveRecord
|
|
89
72
|
end
|
90
73
|
end
|
91
74
|
|
92
|
-
|
93
|
-
|
94
|
-
@error = error
|
95
|
-
end
|
75
|
+
if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
|
76
|
+
include DidYouMean::Correctable
|
96
77
|
|
97
78
|
def corrections
|
98
|
-
if
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
}.reverse.first(4)
|
79
|
+
if owner_class && reflection
|
80
|
+
@corrections ||= begin
|
81
|
+
maybe_these = owner_class.reflections.keys
|
82
|
+
maybe_these -= [reflection.name.to_s] # remove failing reflection
|
83
|
+
DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(reflection.options[:through].to_s)
|
84
|
+
end
|
105
85
|
else
|
106
86
|
[]
|
107
87
|
end
|
108
88
|
end
|
109
89
|
end
|
110
|
-
|
111
|
-
# We may not have DYM, and DYM might not let us register error handlers
|
112
|
-
if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
|
113
|
-
DidYouMean.correct_error(self, Correction)
|
114
|
-
end
|
115
90
|
end
|
116
91
|
|
117
|
-
class HasManyThroughAssociationPolymorphicSourceError < ActiveRecordError
|
92
|
+
class HasManyThroughAssociationPolymorphicSourceError < ActiveRecordError # :nodoc:
|
118
93
|
def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
|
119
94
|
if owner_class_name && reflection && source_reflection
|
120
95
|
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' on the polymorphic object '#{source_reflection.class_name}##{source_reflection.name}' without 'source_type'. Try adding 'source_type: \"#{reflection.name.to_s.classify}\"' to 'has_many :through' definition.")
|
@@ -124,7 +99,7 @@ module ActiveRecord
|
|
124
99
|
end
|
125
100
|
end
|
126
101
|
|
127
|
-
class HasManyThroughAssociationPolymorphicThroughError < ActiveRecordError
|
102
|
+
class HasManyThroughAssociationPolymorphicThroughError < ActiveRecordError # :nodoc:
|
128
103
|
def initialize(owner_class_name = nil, reflection = nil)
|
129
104
|
if owner_class_name && reflection
|
130
105
|
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.")
|
@@ -134,7 +109,7 @@ module ActiveRecord
|
|
134
109
|
end
|
135
110
|
end
|
136
111
|
|
137
|
-
class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError
|
112
|
+
class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError # :nodoc:
|
138
113
|
def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
|
139
114
|
if owner_class_name && reflection && source_reflection
|
140
115
|
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' with a :source_type option if the '#{reflection.through_reflection.class_name}##{source_reflection.name}' is not polymorphic. Try removing :source_type on your association.")
|
@@ -144,7 +119,7 @@ module ActiveRecord
|
|
144
119
|
end
|
145
120
|
end
|
146
121
|
|
147
|
-
class HasOneThroughCantAssociateThroughCollection < ActiveRecordError
|
122
|
+
class HasOneThroughCantAssociateThroughCollection < ActiveRecordError # :nodoc:
|
148
123
|
def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
|
149
124
|
if owner_class_name && reflection && through_reflection
|
150
125
|
super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' where the :through association '#{owner_class_name}##{through_reflection.name}' is a collection. Specify a has_one or belongs_to association in the :through option instead.")
|
@@ -154,7 +129,7 @@ module ActiveRecord
|
|
154
129
|
end
|
155
130
|
end
|
156
131
|
|
157
|
-
class HasOneAssociationPolymorphicThroughError < ActiveRecordError
|
132
|
+
class HasOneAssociationPolymorphicThroughError < ActiveRecordError # :nodoc:
|
158
133
|
def initialize(owner_class_name = nil, reflection = nil)
|
159
134
|
if owner_class_name && reflection
|
160
135
|
super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.")
|
@@ -164,7 +139,7 @@ module ActiveRecord
|
|
164
139
|
end
|
165
140
|
end
|
166
141
|
|
167
|
-
class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError
|
142
|
+
class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError # :nodoc:
|
168
143
|
def initialize(reflection = nil)
|
169
144
|
if reflection
|
170
145
|
through_reflection = reflection.through_reflection
|
@@ -177,7 +152,7 @@ module ActiveRecord
|
|
177
152
|
end
|
178
153
|
end
|
179
154
|
|
180
|
-
class HasManyThroughOrderError < ActiveRecordError
|
155
|
+
class HasManyThroughOrderError < ActiveRecordError # :nodoc:
|
181
156
|
def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
|
182
157
|
if owner_class_name && reflection && through_reflection
|
183
158
|
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' which goes through '#{owner_class_name}##{through_reflection.name}' before the through association is defined.")
|
@@ -187,7 +162,7 @@ module ActiveRecord
|
|
187
162
|
end
|
188
163
|
end
|
189
164
|
|
190
|
-
class ThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError
|
165
|
+
class ThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError # :nodoc:
|
191
166
|
def initialize(owner = nil, reflection = nil)
|
192
167
|
if owner && reflection
|
193
168
|
super("Cannot modify association '#{owner.class.name}##{reflection.name}' because the source reflection class '#{reflection.source_reflection.class_name}' is associated to '#{reflection.through_reflection.class_name}' via :#{reflection.source_reflection.macro}.")
|
@@ -212,13 +187,13 @@ module ActiveRecord
|
|
212
187
|
end
|
213
188
|
end
|
214
189
|
|
215
|
-
class HasManyThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection
|
190
|
+
class HasManyThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection # :nodoc:
|
216
191
|
end
|
217
192
|
|
218
|
-
class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection
|
193
|
+
class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection # :nodoc:
|
219
194
|
end
|
220
195
|
|
221
|
-
class ThroughNestedAssociationsAreReadonly < ActiveRecordError
|
196
|
+
class ThroughNestedAssociationsAreReadonly < ActiveRecordError # :nodoc:
|
222
197
|
def initialize(owner = nil, reflection = nil)
|
223
198
|
if owner && reflection
|
224
199
|
super("Cannot modify association '#{owner.class.name}##{reflection.name}' because it goes through more than one other association.")
|
@@ -228,10 +203,10 @@ module ActiveRecord
|
|
228
203
|
end
|
229
204
|
end
|
230
205
|
|
231
|
-
class HasManyThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly
|
206
|
+
class HasManyThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly # :nodoc:
|
232
207
|
end
|
233
208
|
|
234
|
-
class HasOneThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly
|
209
|
+
class HasOneThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly # :nodoc:
|
235
210
|
end
|
236
211
|
|
237
212
|
# This error is raised when trying to eager load a polymorphic association using a JOIN.
|
@@ -250,7 +225,7 @@ module ActiveRecord
|
|
250
225
|
# This error is raised when trying to destroy a parent instance in N:1 or 1:1 associations
|
251
226
|
# (has_many, has_one) when there is at least 1 child associated instance.
|
252
227
|
# ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project
|
253
|
-
class DeleteRestrictionError < ActiveRecordError
|
228
|
+
class DeleteRestrictionError < ActiveRecordError # :nodoc:
|
254
229
|
def initialize(name = nil)
|
255
230
|
if name
|
256
231
|
super("Cannot delete record because of dependent #{name}")
|
@@ -274,7 +249,7 @@ module ActiveRecord
|
|
274
249
|
autoload :CollectionProxy
|
275
250
|
autoload :ThroughAssociation
|
276
251
|
|
277
|
-
module Builder
|
252
|
+
module Builder # :nodoc:
|
278
253
|
autoload :Association, "active_record/associations/builder/association"
|
279
254
|
autoload :SingularAssociation, "active_record/associations/builder/singular_association"
|
280
255
|
autoload :CollectionAssociation, "active_record/associations/builder/collection_association"
|
@@ -296,6 +271,7 @@ module ActiveRecord
|
|
296
271
|
autoload :Preloader
|
297
272
|
autoload :JoinDependency
|
298
273
|
autoload :AssociationScope
|
274
|
+
autoload :DisableJoinsAssociationScope
|
299
275
|
autoload :AliasTracker
|
300
276
|
end
|
301
277
|
|
@@ -305,7 +281,7 @@ module ActiveRecord
|
|
305
281
|
end
|
306
282
|
|
307
283
|
# Returns the association instance for the given name, instantiating it if it doesn't already exist
|
308
|
-
def association(name)
|
284
|
+
def association(name) # :nodoc:
|
309
285
|
association = association_instance_get(name)
|
310
286
|
|
311
287
|
if association.nil?
|
@@ -328,17 +304,7 @@ module ActiveRecord
|
|
328
304
|
super
|
329
305
|
end
|
330
306
|
|
331
|
-
def reload(*) # :nodoc:
|
332
|
-
clear_association_cache
|
333
|
-
super
|
334
|
-
end
|
335
|
-
|
336
307
|
private
|
337
|
-
# Clears out the association cache.
|
338
|
-
def clear_association_cache
|
339
|
-
@association_cache.clear if persisted?
|
340
|
-
end
|
341
|
-
|
342
308
|
def init_internals
|
343
309
|
@association_cache = {}
|
344
310
|
super
|
@@ -398,6 +364,8 @@ module ActiveRecord
|
|
398
364
|
# create_other(attributes={}) | X | | X
|
399
365
|
# create_other!(attributes={}) | X | | X
|
400
366
|
# reload_other | X | X | X
|
367
|
+
# other_changed? | X | X |
|
368
|
+
# other_previously_changed? | X | X |
|
401
369
|
#
|
402
370
|
# === Collection associations (one-to-many / many-to-many)
|
403
371
|
# | | | has_many
|
@@ -1410,6 +1378,11 @@ module ActiveRecord
|
|
1410
1378
|
# join model. This allows associated records to be built which will automatically create
|
1411
1379
|
# the appropriate join model records when they are saved. (See the 'Association Join Models'
|
1412
1380
|
# section above.)
|
1381
|
+
# [:disable_joins]
|
1382
|
+
# Specifies whether joins should be skipped for an association. If set to true, two or more queries
|
1383
|
+
# will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory
|
1384
|
+
# due to database limitations. This option is only applicable on `has_many :through` associations as
|
1385
|
+
# `has_many` alone do not perform a join.
|
1413
1386
|
# [:source]
|
1414
1387
|
# Specifies the source association name used by #has_many <tt>:through</tt> queries.
|
1415
1388
|
# Only use it if the name cannot be inferred from the association.
|
@@ -1439,7 +1412,8 @@ module ActiveRecord
|
|
1439
1412
|
# Useful for defining methods on associations, especially when they should be shared between multiple
|
1440
1413
|
# association objects.
|
1441
1414
|
# [:strict_loading]
|
1442
|
-
#
|
1415
|
+
# When set to +true+, enforces strict loading every time the associated record is loaded through this
|
1416
|
+
# association.
|
1443
1417
|
# [:ensuring_owner_was]
|
1444
1418
|
# Specifies an instance method to be called on the owner. The method must return true in order for the
|
1445
1419
|
# associated records to be deleted in a background job.
|
@@ -1453,6 +1427,7 @@ module ActiveRecord
|
|
1453
1427
|
# has_many :tags, as: :taggable
|
1454
1428
|
# has_many :reports, -> { readonly }
|
1455
1429
|
# has_many :subscribers, through: :subscriptions, source: :user
|
1430
|
+
# has_many :subscribers, through: :subscriptions, disable_joins: true
|
1456
1431
|
# has_many :comments, strict_loading: true
|
1457
1432
|
def has_many(name, scope = nil, **options, &extension)
|
1458
1433
|
reflection = Builder::HasMany.build(self, name, scope, options, &extension)
|
@@ -1558,8 +1533,21 @@ module ActiveRecord
|
|
1558
1533
|
# source reflection. You can only use a <tt>:through</tt> query through a #has_one
|
1559
1534
|
# or #belongs_to association on the join model.
|
1560
1535
|
#
|
1536
|
+
# If the association on the join model is a #belongs_to, the collection can be modified
|
1537
|
+
# and the records on the <tt>:through</tt> model will be automatically created and removed
|
1538
|
+
# as appropriate. Otherwise, the collection is read-only, so you should manipulate the
|
1539
|
+
# <tt>:through</tt> association directly.
|
1540
|
+
#
|
1561
1541
|
# If you are going to modify the association (rather than just read from it), then it is
|
1562
|
-
# a good idea to set the <tt>:inverse_of</tt> option
|
1542
|
+
# a good idea to set the <tt>:inverse_of</tt> option on the source association on the
|
1543
|
+
# join model. This allows associated records to be built which will automatically create
|
1544
|
+
# the appropriate join model records when they are saved. (See the 'Association Join Models'
|
1545
|
+
# section above.)
|
1546
|
+
# [:disable_joins]
|
1547
|
+
# Specifies whether joins should be skipped for an association. If set to true, two or more queries
|
1548
|
+
# will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory
|
1549
|
+
# due to database limitations. This option is only applicable on `has_one :through` associations as
|
1550
|
+
# `has_one` alone does not perform a join.
|
1563
1551
|
# [:source]
|
1564
1552
|
# Specifies the source association name used by #has_one <tt>:through</tt> queries.
|
1565
1553
|
# Only use it if the name cannot be inferred from the association.
|
@@ -1601,6 +1589,7 @@ module ActiveRecord
|
|
1601
1589
|
# has_one :attachment, as: :attachable
|
1602
1590
|
# has_one :boss, -> { readonly }
|
1603
1591
|
# has_one :club, through: :membership
|
1592
|
+
# has_one :club, through: :membership, disable_joins: true
|
1604
1593
|
# has_one :primary_address, -> { where(primary: true) }, through: :addressables, source: :addressable
|
1605
1594
|
# has_one :credit_card, required: true
|
1606
1595
|
# has_one :credit_card, strict_loading: true
|
@@ -1637,6 +1626,10 @@ module ActiveRecord
|
|
1637
1626
|
# if the record is invalid.
|
1638
1627
|
# [reload_association]
|
1639
1628
|
# Returns the associated object, forcing a database read.
|
1629
|
+
# [association_changed?]
|
1630
|
+
# Returns true if a new associate object has been assigned and the next save will update the foreign key.
|
1631
|
+
# [association_previously_changed?]
|
1632
|
+
# Returns true if the previous save updated the association to reference a new associate object.
|
1640
1633
|
#
|
1641
1634
|
# === Example
|
1642
1635
|
#
|
@@ -1647,6 +1640,8 @@ module ActiveRecord
|
|
1647
1640
|
# * <tt>Post#create_author</tt> (similar to <tt>post.author = Author.new; post.author.save; post.author</tt>)
|
1648
1641
|
# * <tt>Post#create_author!</tt> (similar to <tt>post.author = Author.new; post.author.save!; post.author</tt>)
|
1649
1642
|
# * <tt>Post#reload_author</tt>
|
1643
|
+
# * <tt>Post#author_changed?</tt>
|
1644
|
+
# * <tt>Post#author_previously_changed?</tt>
|
1650
1645
|
# The declaration can also include an +options+ hash to specialize the behavior of the association.
|
1651
1646
|
#
|
1652
1647
|
# === Scopes
|
@@ -1780,7 +1775,7 @@ module ActiveRecord
|
|
1780
1775
|
# The join table should not have a primary key or a model associated with it. You must manually generate the
|
1781
1776
|
# join table with a migration such as this:
|
1782
1777
|
#
|
1783
|
-
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[
|
1778
|
+
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[7.0]
|
1784
1779
|
# def change
|
1785
1780
|
# create_join_table :developers, :projects
|
1786
1781
|
# end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class AsynchronousQueriesTracker # :nodoc:
|
5
|
+
module NullSession # :nodoc:
|
6
|
+
class << self
|
7
|
+
def active?
|
8
|
+
true
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Session # :nodoc:
|
14
|
+
def initialize
|
15
|
+
@active = true
|
16
|
+
end
|
17
|
+
|
18
|
+
def active?
|
19
|
+
@active
|
20
|
+
end
|
21
|
+
|
22
|
+
def finalize
|
23
|
+
@active = false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class << self
|
28
|
+
def install_executor_hooks(executor = ActiveSupport::Executor)
|
29
|
+
executor.register_hook(self)
|
30
|
+
end
|
31
|
+
|
32
|
+
def run
|
33
|
+
ActiveRecord::Base.asynchronous_queries_tracker.start_session
|
34
|
+
end
|
35
|
+
|
36
|
+
def complete(asynchronous_queries_tracker)
|
37
|
+
asynchronous_queries_tracker.finalize_session
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
attr_reader :current_session
|
42
|
+
|
43
|
+
def initialize
|
44
|
+
@current_session = NullSession
|
45
|
+
end
|
46
|
+
|
47
|
+
def start_session
|
48
|
+
@current_session = Session.new
|
49
|
+
self
|
50
|
+
end
|
51
|
+
|
52
|
+
def finalize_session
|
53
|
+
@current_session.finalize
|
54
|
+
@current_session = NullSession
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|