activerecord 7.1.3.4 → 7.2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +652 -2032
- data/README.rdoc +15 -15
- data/examples/performance.rb +2 -2
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/alias_tracker.rb +25 -19
- data/lib/active_record/associations/association.rb +15 -8
- data/lib/active_record/associations/belongs_to_association.rb +18 -11
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
- data/lib/active_record/associations/builder/belongs_to.rb +1 -0
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +2 -2
- data/lib/active_record/associations/builder/has_many.rb +3 -4
- data/lib/active_record/associations/builder/has_one.rb +3 -4
- data/lib/active_record/associations/collection_association.rb +11 -5
- data/lib/active_record/associations/collection_proxy.rb +14 -1
- data/lib/active_record/associations/errors.rb +265 -0
- data/lib/active_record/associations/has_many_association.rb +3 -3
- data/lib/active_record/associations/has_many_through_association.rb +7 -1
- data/lib/active_record/associations/has_one_association.rb +2 -2
- data/lib/active_record/associations/join_dependency/join_association.rb +30 -27
- data/lib/active_record/associations/join_dependency.rb +10 -12
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +2 -1
- data/lib/active_record/associations/preloader/branch.rb +7 -1
- data/lib/active_record/associations/preloader/through_association.rb +1 -3
- data/lib/active_record/associations/singular_association.rb +6 -0
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +62 -289
- data/lib/active_record/attribute_assignment.rb +0 -2
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +2 -2
- data/lib/active_record/attribute_methods/primary_key.rb +23 -55
- data/lib/active_record/attribute_methods/read.rb +4 -16
- data/lib/active_record/attribute_methods/serialization.rb +4 -24
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +11 -6
- data/lib/active_record/attribute_methods/write.rb +3 -3
- data/lib/active_record/attribute_methods.rb +89 -58
- data/lib/active_record/attributes.rb +61 -47
- data/lib/active_record/autosave_association.rb +17 -31
- data/lib/active_record/base.rb +2 -3
- data/lib/active_record/callbacks.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +24 -107
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +1 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +270 -58
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +35 -18
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +190 -75
- data/lib/active_record/connection_adapters/abstract/quoting.rb +65 -91
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +23 -10
- data/lib/active_record/connection_adapters/abstract/transaction.rb +125 -62
- data/lib/active_record/connection_adapters/abstract_adapter.rb +38 -59
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +73 -19
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +9 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +43 -48
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +8 -1
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +16 -15
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +20 -32
- data/lib/active_record/connection_adapters/pool_config.rb +7 -6
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +27 -4
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +58 -58
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +20 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +18 -12
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +29 -24
- data/lib/active_record/connection_adapters/schema_cache.rb +123 -128
- data/lib/active_record/connection_adapters/sqlite3/column.rb +14 -1
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +10 -6
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +44 -46
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +13 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +25 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +127 -77
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +15 -15
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +32 -65
- data/lib/active_record/connection_adapters.rb +121 -0
- data/lib/active_record/connection_handling.rb +56 -41
- data/lib/active_record/core.rb +93 -40
- data/lib/active_record/counter_cache.rb +23 -10
- data/lib/active_record/database_configurations/connection_url_resolver.rb +8 -3
- data/lib/active_record/database_configurations/database_config.rb +19 -4
- data/lib/active_record/database_configurations/hash_config.rb +44 -36
- data/lib/active_record/database_configurations/url_config.rb +20 -1
- data/lib/active_record/database_configurations.rb +1 -1
- data/lib/active_record/delegated_type.rb +30 -6
- data/lib/active_record/destroy_association_async_job.rb +1 -1
- data/lib/active_record/dynamic_matchers.rb +2 -2
- data/lib/active_record/encryption/encryptable_record.rb +3 -3
- data/lib/active_record/encryption/encrypted_attribute_type.rb +26 -6
- data/lib/active_record/encryption/encryptor.rb +18 -3
- data/lib/active_record/encryption/key_provider.rb +1 -1
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +4 -0
- data/lib/active_record/encryption/null_encryptor.rb +4 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
- data/lib/active_record/encryption/scheme.rb +8 -4
- data/lib/active_record/encryption.rb +2 -0
- data/lib/active_record/enum.rb +19 -2
- data/lib/active_record/errors.rb +46 -20
- data/lib/active_record/explain.rb +13 -24
- data/lib/active_record/fixtures.rb +37 -31
- data/lib/active_record/future_result.rb +17 -4
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +4 -2
- data/lib/active_record/insert_all.rb +18 -15
- data/lib/active_record/integration.rb +4 -1
- data/lib/active_record/internal_metadata.rb +48 -34
- data/lib/active_record/locking/optimistic.rb +8 -7
- data/lib/active_record/log_subscriber.rb +0 -21
- data/lib/active_record/marshalling.rb +4 -1
- data/lib/active_record/message_pack.rb +2 -2
- data/lib/active_record/migration/command_recorder.rb +2 -3
- data/lib/active_record/migration/compatibility.rb +11 -3
- data/lib/active_record/migration/default_strategy.rb +4 -5
- data/lib/active_record/migration/pending_migration_connection.rb +2 -2
- data/lib/active_record/migration.rb +85 -76
- data/lib/active_record/model_schema.rb +38 -70
- data/lib/active_record/nested_attributes.rb +24 -5
- data/lib/active_record/normalization.rb +3 -7
- data/lib/active_record/persistence.rb +32 -354
- data/lib/active_record/query_cache.rb +19 -8
- data/lib/active_record/query_logs.rb +15 -0
- data/lib/active_record/query_logs_formatter.rb +1 -1
- data/lib/active_record/querying.rb +21 -9
- data/lib/active_record/railtie.rb +50 -68
- data/lib/active_record/railties/controller_runtime.rb +13 -4
- data/lib/active_record/railties/databases.rake +42 -45
- data/lib/active_record/reflection.rb +106 -38
- data/lib/active_record/relation/batches/batch_enumerator.rb +15 -2
- data/lib/active_record/relation/batches.rb +14 -8
- data/lib/active_record/relation/calculations.rb +96 -63
- data/lib/active_record/relation/delegation.rb +8 -11
- data/lib/active_record/relation/finder_methods.rb +16 -2
- data/lib/active_record/relation/merger.rb +4 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +9 -3
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +6 -1
- data/lib/active_record/relation/predicate_builder.rb +3 -3
- data/lib/active_record/relation/query_methods.rb +245 -65
- data/lib/active_record/relation/record_fetch_warning.rb +3 -0
- data/lib/active_record/relation/spawn_methods.rb +2 -18
- data/lib/active_record/relation/where_clause.rb +7 -19
- data/lib/active_record/relation.rb +500 -66
- data/lib/active_record/result.rb +32 -45
- data/lib/active_record/runtime_registry.rb +39 -0
- data/lib/active_record/sanitization.rb +24 -19
- data/lib/active_record/schema.rb +8 -6
- data/lib/active_record/schema_dumper.rb +19 -9
- data/lib/active_record/schema_migration.rb +30 -14
- data/lib/active_record/scoping/named.rb +1 -0
- data/lib/active_record/signed_id.rb +20 -1
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/table_metadata.rb +1 -10
- data/lib/active_record/tasks/database_tasks.rb +98 -48
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -1
- data/lib/active_record/test_fixtures.rb +87 -89
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +5 -3
- data/lib/active_record/token_for.rb +22 -12
- data/lib/active_record/touch_later.rb +1 -1
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +70 -14
- data/lib/active_record/translation.rb +0 -2
- data/lib/active_record/type/serialized.rb +1 -3
- data/lib/active_record/type_caster/connection.rb +4 -4
- data/lib/active_record/validations/associated.rb +9 -3
- data/lib/active_record/validations/uniqueness.rb +15 -10
- data/lib/active_record/validations.rb +4 -1
- data/lib/active_record.rb +150 -41
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/collectors/bind.rb +2 -0
- data/lib/arel/collectors/composite.rb +7 -0
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- data/lib/arel/nodes/binary.rb +0 -6
- data/lib/arel/nodes/bound_sql_literal.rb +9 -5
- data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
- data/lib/arel/nodes/node.rb +4 -3
- data/lib/arel/nodes/sql_literal.rb +7 -0
- data/lib/arel/nodes.rb +2 -2
- data/lib/arel/predications.rb +1 -1
- data/lib/arel/select_manager.rb +1 -1
- data/lib/arel/tree_manager.rb +8 -3
- data/lib/arel/update_manager.rb +2 -1
- data/lib/arel/visitors/dot.rb +1 -0
- data/lib/arel/visitors/mysql.rb +9 -4
- data/lib/arel/visitors/postgresql.rb +1 -12
- data/lib/arel/visitors/sqlite.rb +25 -0
- data/lib/arel/visitors/to_sql.rb +31 -17
- data/lib/arel.rb +7 -3
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
- metadata +21 -15
@@ -1,268 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
|
-
class AssociationNotFoundError < ConfigurationError # :nodoc:
|
5
|
-
attr_reader :record, :association_name
|
6
|
-
|
7
|
-
def initialize(record = nil, association_name = nil)
|
8
|
-
@record = record
|
9
|
-
@association_name = association_name
|
10
|
-
if record && association_name
|
11
|
-
super("Association named '#{association_name}' was not found on #{record.class.name}; perhaps you misspelled it?")
|
12
|
-
else
|
13
|
-
super("Association was not found.")
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
|
18
|
-
include DidYouMean::Correctable
|
19
|
-
|
20
|
-
def corrections
|
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
|
26
|
-
else
|
27
|
-
[]
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
class InverseOfAssociationNotFoundError < ActiveRecordError # :nodoc:
|
34
|
-
attr_reader :reflection, :associated_class
|
35
|
-
|
36
|
-
def initialize(reflection = nil, associated_class = nil)
|
37
|
-
if reflection
|
38
|
-
@reflection = reflection
|
39
|
-
@associated_class = associated_class.nil? ? reflection.klass : associated_class
|
40
|
-
super("Could not find the inverse association for #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{associated_class.nil? ? reflection.class_name : associated_class.name})")
|
41
|
-
else
|
42
|
-
super("Could not find the inverse association.")
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
|
47
|
-
include DidYouMean::Correctable
|
48
|
-
|
49
|
-
def corrections
|
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
|
55
|
-
else
|
56
|
-
[]
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
class InverseOfAssociationRecursiveError < ActiveRecordError # :nodoc:
|
63
|
-
attr_reader :reflection
|
64
|
-
def initialize(reflection = nil)
|
65
|
-
if reflection
|
66
|
-
@reflection = reflection
|
67
|
-
super("Inverse association #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{reflection.class_name}) is recursive.")
|
68
|
-
else
|
69
|
-
super("Inverse association is recursive.")
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
class HasManyThroughAssociationNotFoundError < ActiveRecordError # :nodoc:
|
75
|
-
attr_reader :owner_class, :reflection
|
76
|
-
|
77
|
-
def initialize(owner_class = nil, reflection = nil)
|
78
|
-
if owner_class && reflection
|
79
|
-
@owner_class = owner_class
|
80
|
-
@reflection = reflection
|
81
|
-
super("Could not find the association #{reflection.options[:through].inspect} in model #{owner_class.name}")
|
82
|
-
else
|
83
|
-
super("Could not find the association.")
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
|
88
|
-
include DidYouMean::Correctable
|
89
|
-
|
90
|
-
def corrections
|
91
|
-
if owner_class && reflection
|
92
|
-
@corrections ||= begin
|
93
|
-
maybe_these = owner_class.reflections.keys
|
94
|
-
maybe_these -= [reflection.name.to_s] # remove failing reflection
|
95
|
-
DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(reflection.options[:through].to_s)
|
96
|
-
end
|
97
|
-
else
|
98
|
-
[]
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
class HasManyThroughAssociationPolymorphicSourceError < ActiveRecordError # :nodoc:
|
105
|
-
def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
|
106
|
-
if owner_class_name && reflection && source_reflection
|
107
|
-
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.")
|
108
|
-
else
|
109
|
-
super("Cannot have a has_many :through association.")
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
class HasManyThroughAssociationPolymorphicThroughError < ActiveRecordError # :nodoc:
|
115
|
-
def initialize(owner_class_name = nil, reflection = nil)
|
116
|
-
if owner_class_name && reflection
|
117
|
-
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}'.")
|
118
|
-
else
|
119
|
-
super("Cannot have a has_many :through association.")
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError # :nodoc:
|
125
|
-
def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
|
126
|
-
if owner_class_name && reflection && source_reflection
|
127
|
-
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.")
|
128
|
-
else
|
129
|
-
super("Cannot have a has_many :through association.")
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
class HasOneThroughCantAssociateThroughCollection < ActiveRecordError # :nodoc:
|
135
|
-
def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
|
136
|
-
if owner_class_name && reflection && through_reflection
|
137
|
-
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.")
|
138
|
-
else
|
139
|
-
super("Cannot have a has_one :through association.")
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
class HasOneAssociationPolymorphicThroughError < ActiveRecordError # :nodoc:
|
145
|
-
def initialize(owner_class_name = nil, reflection = nil)
|
146
|
-
if owner_class_name && reflection
|
147
|
-
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}'.")
|
148
|
-
else
|
149
|
-
super("Cannot have a has_one :through association.")
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError # :nodoc:
|
155
|
-
def initialize(reflection = nil)
|
156
|
-
if reflection
|
157
|
-
through_reflection = reflection.through_reflection
|
158
|
-
source_reflection_names = reflection.source_reflection_names
|
159
|
-
source_associations = reflection.through_reflection.klass._reflections.keys
|
160
|
-
super("Could not find the source association(s) #{source_reflection_names.collect(&:inspect).to_sentence(two_words_connector: ' or ', last_word_connector: ', or ')} in model #{through_reflection.klass}. Try 'has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}, :source => <name>'. Is it one of #{source_associations.to_sentence(two_words_connector: ' or ', last_word_connector: ', or ')}?")
|
161
|
-
else
|
162
|
-
super("Could not find the source association(s).")
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
class HasManyThroughOrderError < ActiveRecordError # :nodoc:
|
168
|
-
def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
|
169
|
-
if owner_class_name && reflection && through_reflection
|
170
|
-
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.")
|
171
|
-
else
|
172
|
-
super("Cannot have a has_many :through association before the through association is defined.")
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
class ThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError # :nodoc:
|
178
|
-
def initialize(owner = nil, reflection = nil)
|
179
|
-
if owner && reflection
|
180
|
-
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}.")
|
181
|
-
else
|
182
|
-
super("Cannot modify association.")
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
class CompositePrimaryKeyMismatchError < ActiveRecordError # :nodoc:
|
188
|
-
attr_reader :reflection
|
189
|
-
|
190
|
-
def initialize(reflection = nil)
|
191
|
-
if reflection
|
192
|
-
if reflection.has_one? || reflection.collection?
|
193
|
-
super("Association #{reflection.active_record}##{reflection.name} primary key #{reflection.active_record_primary_key} doesn't match with foreign key #{reflection.foreign_key}. Please specify query_constraints, or primary_key and foreign_key values.")
|
194
|
-
else
|
195
|
-
super("Association #{reflection.active_record}##{reflection.name} primary key #{reflection.association_primary_key} doesn't match with foreign key #{reflection.foreign_key}. Please specify query_constraints, or primary_key and foreign_key values.")
|
196
|
-
end
|
197
|
-
else
|
198
|
-
super("Association primary key doesn't match with foreign key.")
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
class AmbiguousSourceReflectionForThroughAssociation < ActiveRecordError # :nodoc:
|
204
|
-
def initialize(klass, macro, association_name, options, possible_sources)
|
205
|
-
example_options = options.dup
|
206
|
-
example_options[:source] = possible_sources.first
|
207
|
-
|
208
|
-
super("Ambiguous source reflection for through association. Please " \
|
209
|
-
"specify a :source directive on your declaration like:\n" \
|
210
|
-
"\n" \
|
211
|
-
" class #{klass} < ActiveRecord::Base\n" \
|
212
|
-
" #{macro} :#{association_name}, #{example_options}\n" \
|
213
|
-
" end"
|
214
|
-
)
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
class HasManyThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection # :nodoc:
|
219
|
-
end
|
220
|
-
|
221
|
-
class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection # :nodoc:
|
222
|
-
end
|
223
|
-
|
224
|
-
class ThroughNestedAssociationsAreReadonly < ActiveRecordError # :nodoc:
|
225
|
-
def initialize(owner = nil, reflection = nil)
|
226
|
-
if owner && reflection
|
227
|
-
super("Cannot modify association '#{owner.class.name}##{reflection.name}' because it goes through more than one other association.")
|
228
|
-
else
|
229
|
-
super("Through nested associations are read-only.")
|
230
|
-
end
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
class HasManyThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly # :nodoc:
|
235
|
-
end
|
236
|
-
|
237
|
-
class HasOneThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly # :nodoc:
|
238
|
-
end
|
239
|
-
|
240
|
-
# This error is raised when trying to eager load a polymorphic association using a JOIN.
|
241
|
-
# Eager loading polymorphic associations is only possible with
|
242
|
-
# {ActiveRecord::Relation#preload}[rdoc-ref:QueryMethods#preload].
|
243
|
-
class EagerLoadPolymorphicError < ActiveRecordError
|
244
|
-
def initialize(reflection = nil)
|
245
|
-
if reflection
|
246
|
-
super("Cannot eagerly load the polymorphic association #{reflection.name.inspect}")
|
247
|
-
else
|
248
|
-
super("Eager load polymorphic error.")
|
249
|
-
end
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
# This error is raised when trying to destroy a parent instance in N:1 or 1:1 associations
|
254
|
-
# (has_many, has_one) when there is at least 1 child associated instance.
|
255
|
-
# ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project
|
256
|
-
class DeleteRestrictionError < ActiveRecordError # :nodoc:
|
257
|
-
def initialize(name = nil)
|
258
|
-
if name
|
259
|
-
super("Cannot delete record because of dependent #{name}")
|
260
|
-
else
|
261
|
-
super("Delete restriction error.")
|
262
|
-
end
|
263
|
-
end
|
264
|
-
end
|
265
|
-
|
266
4
|
# See ActiveRecord::Associations::ClassMethods for documentation.
|
267
5
|
module Associations # :nodoc:
|
268
6
|
extend ActiveSupport::Autoload
|
@@ -799,7 +537,7 @@ module ActiveRecord
|
|
799
537
|
# @group.avatars << Avatar.new # this would work if User belonged_to Avatar rather than the other way around
|
800
538
|
# @group.avatars.delete(@group.avatars.last) # so would this
|
801
539
|
#
|
802
|
-
#
|
540
|
+
# === Setting Inverses
|
803
541
|
#
|
804
542
|
# If you are using a #belongs_to on the join model, it is a good idea to set the
|
805
543
|
# <tt>:inverse_of</tt> option on the #belongs_to, which will mean that the following example
|
@@ -1461,8 +1199,11 @@ module ActiveRecord
|
|
1461
1199
|
# If you are going to modify the association (rather than just read from it), then it is
|
1462
1200
|
# a good idea to set the <tt>:inverse_of</tt> option on the source association on the
|
1463
1201
|
# join model. This allows associated records to be built which will automatically create
|
1464
|
-
# the appropriate join model records when they are saved.
|
1465
|
-
#
|
1202
|
+
# the appropriate join model records when they are saved. See
|
1203
|
+
# {Association Join Models}[rdoc-ref:Associations::ClassMethods@Association+Join+Models]
|
1204
|
+
# and {Setting Inverses}[rdoc-ref:Associations::ClassMethods@Setting+Inverses] for
|
1205
|
+
# more detail.
|
1206
|
+
#
|
1466
1207
|
# [+:disable_joins+]
|
1467
1208
|
# Specifies whether joins should be skipped for an association. If set to true, two or more queries
|
1468
1209
|
# will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory
|
@@ -1491,7 +1232,8 @@ module ActiveRecord
|
|
1491
1232
|
# [+:inverse_of+]
|
1492
1233
|
# Specifies the name of the #belongs_to association on the associated object
|
1493
1234
|
# that is the inverse of this #has_many association.
|
1494
|
-
# See
|
1235
|
+
# See {Bi-directional associations}[rdoc-ref:Associations::ClassMethods@Bi-directional+associations]
|
1236
|
+
# for more detail.
|
1495
1237
|
# [+:extend+]
|
1496
1238
|
# Specifies a module or array of modules that will be extended into the association object returned.
|
1497
1239
|
# Useful for defining methods on associations, especially when they should be shared between multiple
|
@@ -1506,6 +1248,13 @@ module ActiveRecord
|
|
1506
1248
|
# Serves as a composite foreign key. Defines the list of columns to be used to query the associated object.
|
1507
1249
|
# This is an optional option. By default Rails will attempt to derive the value automatically.
|
1508
1250
|
# When the value is set the Array size must match associated model's primary key or +query_constraints+ size.
|
1251
|
+
# [+:index_errors+]
|
1252
|
+
# Allows differentiation of multiple validation errors from the association records, by including
|
1253
|
+
# an index in the error attribute name, e.g. +roles[2].level+.
|
1254
|
+
# When set to +true+, the index is based on association order, i.e. database order, with yet to be
|
1255
|
+
# persisted new records placed at the end.
|
1256
|
+
# When set to +:nested_attributes_order+, the index is based on the record order received by
|
1257
|
+
# nested attributes setter, when accepts_nested_attributes_for is used.
|
1509
1258
|
#
|
1510
1259
|
# Option examples:
|
1511
1260
|
# has_many :comments, -> { order("posted_on") }
|
@@ -1519,15 +1268,18 @@ module ActiveRecord
|
|
1519
1268
|
# has_many :subscribers, through: :subscriptions, disable_joins: true
|
1520
1269
|
# has_many :comments, strict_loading: true
|
1521
1270
|
# has_many :comments, query_constraints: [:blog_id, :post_id]
|
1271
|
+
# has_many :comments, index_errors: :nested_attributes_order
|
1522
1272
|
def has_many(name, scope = nil, **options, &extension)
|
1523
1273
|
reflection = Builder::HasMany.build(self, name, scope, options, &extension)
|
1524
1274
|
Reflection.add_reflection self, name, reflection
|
1525
1275
|
end
|
1526
1276
|
|
1527
|
-
# Specifies a one-to-one association with another class. This method
|
1528
|
-
# if the other class contains the foreign key. If
|
1529
|
-
#
|
1530
|
-
#
|
1277
|
+
# Specifies a one-to-one association with another class. This method
|
1278
|
+
# should only be used if the other class contains the foreign key. If
|
1279
|
+
# the current class contains the foreign key, then you should use
|
1280
|
+
# #belongs_to instead. See {Is it a belongs_to or has_one
|
1281
|
+
# association?}[rdoc-ref:Associations::ClassMethods@Is+it+a+-23belongs_to+or+-23has_one+association-3F]
|
1282
|
+
# for more detail on when to use #has_one and when to use #belongs_to.
|
1531
1283
|
#
|
1532
1284
|
# The following methods for retrieval and query of a single associated object will be added:
|
1533
1285
|
#
|
@@ -1642,8 +1394,10 @@ module ActiveRecord
|
|
1642
1394
|
# If you are going to modify the association (rather than just read from it), then it is
|
1643
1395
|
# a good idea to set the <tt>:inverse_of</tt> option on the source association on the
|
1644
1396
|
# join model. This allows associated records to be built which will automatically create
|
1645
|
-
# the appropriate join model records when they are saved.
|
1646
|
-
#
|
1397
|
+
# the appropriate join model records when they are saved. See
|
1398
|
+
# {Association Join Models}[rdoc-ref:Associations::ClassMethods@Association+Join+Models]
|
1399
|
+
# and {Setting Inverses}[rdoc-ref:Associations::ClassMethods@Setting+Inverses] for
|
1400
|
+
# more detail.
|
1647
1401
|
# [+:disable_joins+]
|
1648
1402
|
# Specifies whether joins should be skipped for an association. If set to true, two or more queries
|
1649
1403
|
# will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory
|
@@ -1661,9 +1415,14 @@ module ActiveRecord
|
|
1661
1415
|
# When set to +true+, validates new objects added to association when saving the parent object. +false+ by default.
|
1662
1416
|
# If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
|
1663
1417
|
# [+:autosave+]
|
1664
|
-
# If true
|
1665
|
-
# when saving the parent object.
|
1666
|
-
#
|
1418
|
+
# If +true+, always saves the associated object or destroys it if marked for destruction,
|
1419
|
+
# when saving the parent object.
|
1420
|
+
# If +false+, never save or destroy the associated object.
|
1421
|
+
#
|
1422
|
+
# By default, only saves the associated object if it's a new record. Setting this option
|
1423
|
+
# to +true+ also enables validations on the associated object unless explicitly disabled
|
1424
|
+
# with <tt>validate: false</tt>. This is because saving an object with invalid associated
|
1425
|
+
# objects would fail, so any associated objects will go through validation checks.
|
1667
1426
|
#
|
1668
1427
|
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
|
1669
1428
|
# <tt>:autosave</tt> to <tt>true</tt>.
|
@@ -1676,7 +1435,8 @@ module ActiveRecord
|
|
1676
1435
|
# [+:inverse_of+]
|
1677
1436
|
# Specifies the name of the #belongs_to association on the associated object
|
1678
1437
|
# that is the inverse of this #has_one association.
|
1679
|
-
# See
|
1438
|
+
# See {Bi-directional associations}[rdoc-ref:Associations::ClassMethods@Bi-directional+associations]
|
1439
|
+
# for more detail.
|
1680
1440
|
# [+:required+]
|
1681
1441
|
# When set to +true+, the association will also have its presence validated.
|
1682
1442
|
# This will validate the association itself, not the id. You can use
|
@@ -1710,10 +1470,12 @@ module ActiveRecord
|
|
1710
1470
|
Reflection.add_reflection self, name, reflection
|
1711
1471
|
end
|
1712
1472
|
|
1713
|
-
# Specifies a one-to-one association with another class. This method
|
1714
|
-
# if this class contains the foreign key. If the
|
1715
|
-
# then you should use #has_one
|
1716
|
-
#
|
1473
|
+
# Specifies a one-to-one association with another class. This method
|
1474
|
+
# should only be used if this class contains the foreign key. If the
|
1475
|
+
# other class contains the foreign key, then you should use #has_one
|
1476
|
+
# instead. See {Is it a belongs_to or has_one
|
1477
|
+
# association?}[rdoc-ref:Associations::ClassMethods@Is+it+a+-23belongs_to+or+-23has_one+association-3F]
|
1478
|
+
# for more detail on when to use #has_one and when to use #belongs_to.
|
1717
1479
|
#
|
1718
1480
|
# Methods will be added for retrieval and query for a single associated object, for which
|
1719
1481
|
# this object holds an id:
|
@@ -1816,15 +1578,25 @@ module ActiveRecord
|
|
1816
1578
|
# named <tt>#{table_name}_count</tt> (such as +comments_count+ for a belonging Comment class)
|
1817
1579
|
# is used on the associate class (such as a Post class) - that is the migration for
|
1818
1580
|
# <tt>#{table_name}_count</tt> is created on the associate class (such that <tt>Post.comments_count</tt> will
|
1819
|
-
# return the count cached
|
1581
|
+
# return the count cached). You can also specify a custom counter
|
1820
1582
|
# cache column by providing a column name instead of a +true+/+false+ value to this
|
1821
1583
|
# option (e.g., <tt>counter_cache: :my_custom_counter</tt>.)
|
1822
|
-
#
|
1823
|
-
#
|
1824
|
-
#
|
1825
|
-
#
|
1584
|
+
#
|
1585
|
+
# Starting to use counter caches on existing large tables can be troublesome, because the column
|
1586
|
+
# values must be backfilled separately of the column addition (to not lock the table for too long)
|
1587
|
+
# and before the use of +:counter_cache+ (otherwise methods like +size+/+any?+/etc, which use
|
1588
|
+
# counter caches internally, can produce incorrect results). To safely backfill the values while keeping
|
1589
|
+
# counter cache columns updated with the child records creation/removal and to avoid the mentioned methods
|
1590
|
+
# use the possibly incorrect counter cache column values and always get the results from the database,
|
1591
|
+
# use <tt>counter_cache: { active: false }</tt>.
|
1592
|
+
# If you also need to specify a custom column name, use <tt>counter_cache: { active: false, column: :my_custom_counter }</tt>.
|
1593
|
+
#
|
1826
1594
|
# Note: If you've enabled the counter cache, then you may want to add the counter cache attribute
|
1827
1595
|
# to the +attr_readonly+ list in the associated classes (e.g. <tt>class Post; attr_readonly :comments_count; end</tt>).
|
1596
|
+
# [+:polymorphic+]
|
1597
|
+
# Specify this association is a polymorphic association by passing +true+.
|
1598
|
+
# Note: Since polymorphic associations rely on storing class names in the database, make sure to update the class names in the
|
1599
|
+
# <tt>*_type</tt> polymorphic type column of the corresponding rows.
|
1828
1600
|
# [+:validate+]
|
1829
1601
|
# When set to +true+, validates new objects added to association when saving the parent object. +false+ by default.
|
1830
1602
|
# If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
|
@@ -1845,7 +1617,8 @@ module ActiveRecord
|
|
1845
1617
|
# [+:inverse_of+]
|
1846
1618
|
# Specifies the name of the #has_one or #has_many association on the associated
|
1847
1619
|
# object that is the inverse of this #belongs_to association.
|
1848
|
-
# See
|
1620
|
+
# See {Bi-directional associations}[rdoc-ref:Associations::ClassMethods@Bi-directional+associations]
|
1621
|
+
# for more detail.
|
1849
1622
|
# [+:optional+]
|
1850
1623
|
# When set to +true+, the association will not have its presence validated.
|
1851
1624
|
# [+:required+]
|
@@ -1882,7 +1655,7 @@ module ActiveRecord
|
|
1882
1655
|
# belongs_to :user, optional: true
|
1883
1656
|
# belongs_to :account, default: -> { company.account }
|
1884
1657
|
# belongs_to :account, strict_loading: true
|
1885
|
-
#
|
1658
|
+
# belongs_to :note, query_constraints: [:organization_id, :note_id]
|
1886
1659
|
def belongs_to(name, scope = nil, **options)
|
1887
1660
|
reflection = Builder::BelongsTo.build(self, name, scope, options)
|
1888
1661
|
Reflection.add_reflection self, name, reflection
|
@@ -1905,7 +1678,7 @@ module ActiveRecord
|
|
1905
1678
|
# The join table should not have a primary key or a model associated with it. You must manually generate the
|
1906
1679
|
# join table with a migration such as this:
|
1907
1680
|
#
|
1908
|
-
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[7.
|
1681
|
+
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[7.2]
|
1909
1682
|
# def change
|
1910
1683
|
# create_join_table :developers, :projects
|
1911
1684
|
# end
|
@@ -2099,7 +1872,7 @@ module ActiveRecord
|
|
2099
1872
|
end
|
2100
1873
|
|
2101
1874
|
has_many name, scope, **hm_options, &extension
|
2102
|
-
_reflections[name
|
1875
|
+
_reflections[name].parent_reflection = habtm_reflection
|
2103
1876
|
end
|
2104
1877
|
end
|
2105
1878
|
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module AttributeMethods
|
5
|
+
module CompositePrimaryKey # :nodoc:
|
6
|
+
# Returns the primary key column's value. If the primary key is composite,
|
7
|
+
# returns an array of the primary key column values.
|
8
|
+
def id
|
9
|
+
if self.class.composite_primary_key?
|
10
|
+
@primary_key.map { |pk| _read_attribute(pk) }
|
11
|
+
else
|
12
|
+
super
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def primary_key_values_present? # :nodoc:
|
17
|
+
if self.class.composite_primary_key?
|
18
|
+
id.all?
|
19
|
+
else
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Sets the primary key column's value. If the primary key is composite,
|
25
|
+
# raises TypeError when the set value not enumerable.
|
26
|
+
def id=(value)
|
27
|
+
if self.class.composite_primary_key?
|
28
|
+
raise TypeError, "Expected value matching #{self.class.primary_key.inspect}, got #{value.inspect}." unless value.is_a?(Enumerable)
|
29
|
+
@primary_key.zip(value) { |attr, value| _write_attribute(attr, value) }
|
30
|
+
else
|
31
|
+
super
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Queries the primary key column's value. If the primary key is composite,
|
36
|
+
# all primary key column values must be queryable.
|
37
|
+
def id?
|
38
|
+
if self.class.composite_primary_key?
|
39
|
+
@primary_key.all? { |col| _query_attribute(col) }
|
40
|
+
else
|
41
|
+
super
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns the primary key column's value before type cast. If the primary key is composite,
|
46
|
+
# returns an array of primary key column values before type cast.
|
47
|
+
def id_before_type_cast
|
48
|
+
if self.class.composite_primary_key?
|
49
|
+
@primary_key.map { |col| attribute_before_type_cast(col) }
|
50
|
+
else
|
51
|
+
super
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns the primary key column's previous value. If the primary key is composite,
|
56
|
+
# returns an array of primary key column previous values.
|
57
|
+
def id_was
|
58
|
+
if self.class.composite_primary_key?
|
59
|
+
@primary_key.map { |col| attribute_was(col) }
|
60
|
+
else
|
61
|
+
super
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns the primary key column's value from the database. If the primary key is composite,
|
66
|
+
# returns an array of primary key column values from database.
|
67
|
+
def id_in_database
|
68
|
+
if self.class.composite_primary_key?
|
69
|
+
@primary_key.map { |col| attribute_in_database(col) }
|
70
|
+
else
|
71
|
+
super
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def id_for_database # :nodoc:
|
76
|
+
if self.class.composite_primary_key?
|
77
|
+
@primary_key.map { |col| @attributes[col].value_for_database }
|
78
|
+
else
|
79
|
+
super
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -31,7 +31,7 @@ module ActiveRecord
|
|
31
31
|
# person.name_in_database # => "Alice"
|
32
32
|
# person.saved_change_to_name? # => true
|
33
33
|
# person.saved_change_to_name # => ["Allison", "Alice"]
|
34
|
-
# person.
|
34
|
+
# person.name_before_last_save # => "Allison"
|
35
35
|
#
|
36
36
|
# Similar to ActiveModel::Dirty, methods can be invoked as
|
37
37
|
# +saved_change_to_name?+ or by passing an argument to the generic method
|
@@ -251,7 +251,7 @@ module ActiveRecord
|
|
251
251
|
changed_attribute_names_to_save
|
252
252
|
else
|
253
253
|
attribute_names.reject do |attr_name|
|
254
|
-
if column_for_attribute(attr_name).
|
254
|
+
if column_for_attribute(attr_name).auto_populated?
|
255
255
|
!attribute_changed?(attr_name)
|
256
256
|
end
|
257
257
|
end
|