activerecord 7.2.0.beta1 → 7.2.0.beta3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +42 -1
- data/lib/active_record/associations/collection_association.rb +3 -3
- data/lib/active_record/associations/errors.rb +265 -0
- data/lib/active_record/associations.rb +0 -262
- data/lib/active_record/attribute_methods/dirty.rb +1 -1
- data/lib/active_record/attribute_methods/read.rb +3 -3
- data/lib/active_record/attribute_methods/write.rb +3 -3
- data/lib/active_record/attribute_methods.rb +8 -6
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +29 -13
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -0
- data/lib/active_record/connection_adapters/abstract/transaction.rb +69 -9
- data/lib/active_record/connection_adapters/abstract_adapter.rb +8 -0
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +1 -1
- data/lib/active_record/database_configurations/database_config.rb +4 -0
- data/lib/active_record/enum.rb +1 -1
- data/lib/active_record/errors.rb +20 -8
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/railtie.rb +3 -4
- data/lib/active_record/railties/databases.rake +1 -1
- data/lib/active_record/relation/calculations.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +22 -10
- data/lib/active_record/signed_id.rb +9 -0
- data/lib/active_record/tasks/database_tasks.rb +2 -2
- data/lib/active_record/test_fixtures.rb +10 -3
- data/lib/active_record/timestamp.rb +1 -1
- data/lib/active_record/transaction.rb +106 -42
- data/lib/active_record/transactions.rb +29 -2
- data/lib/active_record.rb +5 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
- metadata +11 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0a80eeb42f7130f9c9b8f9b9980959b202c550f1cf958326ffb3364161435b5f
|
4
|
+
data.tar.gz: b875a8e003cfce381c29733acf6c3f019ffed72a52a1f01be123913294ea31de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0eb8b60fa9d521a514799b6e5f5a5d1adaac422270b20245849ade043cd45aa485d0a17b57d163c641bc3ae29fa5700dbfa11c55451858de0d0b1647a97a666b
|
7
|
+
data.tar.gz: 68f46c24553e6c1f85751aa223a53e186abd1ec8a744e3803709552e33bbe757193498141af13b918646bc83b1bcb83bee5a2e58f3f1278d785e54a3c444ca32
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,44 @@
|
|
1
|
+
## Rails 7.2.0.beta3 (July 11, 2024) ##
|
2
|
+
|
3
|
+
* Add condensed `#inspect` for `ConnectionPool`, `AbstractAdapter`, and
|
4
|
+
`DatabaseConfig`.
|
5
|
+
|
6
|
+
*Hartley McGuire*
|
7
|
+
|
8
|
+
* Fixed a memory performance issue in Active Record attribute methods definition.
|
9
|
+
|
10
|
+
*Jean Boussier*
|
11
|
+
|
12
|
+
* Define the new Active Support notification event `start_transaction.active_record`.
|
13
|
+
|
14
|
+
This event is fired when database transactions or savepoints start, and
|
15
|
+
complements `transaction.active_record`, which is emitted when they finish.
|
16
|
+
|
17
|
+
The payload has the transaction (`:transaction`) and the connection (`:connection`).
|
18
|
+
|
19
|
+
*Xavier Noria*
|
20
|
+
|
21
|
+
* Fix an issue where the IDs reader method did not return expected results
|
22
|
+
for preloaded associations in models using composite primary keys.
|
23
|
+
|
24
|
+
*Jay Ang*
|
25
|
+
|
26
|
+
|
27
|
+
## Rails 7.2.0.beta2 (June 04, 2024) ##
|
28
|
+
|
29
|
+
* The payload of `sql.active_record` Active Support notifications now has the current transaction in the `:transaction` key.
|
30
|
+
|
31
|
+
*Xavier Noria*
|
32
|
+
|
33
|
+
* The payload of `transaction.active_record` Active Support notifications now has the transaction the event is related to in the `:transaction` key.
|
34
|
+
|
35
|
+
*Xavier Noria*
|
36
|
+
|
37
|
+
* Define `ActiveRecord::Transaction#uuid`, which returns a UUID for the database transaction. This may be helpful when tracing database activity. These UUIDs are generated only on demand.
|
38
|
+
|
39
|
+
*Xavier Noria*
|
40
|
+
|
41
|
+
|
1
42
|
## Rails 7.2.0.beta1 (May 29, 2024) ##
|
2
43
|
|
3
44
|
* Fix inference of association model on nested models with the same demodularized name.
|
@@ -393,7 +434,7 @@
|
|
393
434
|
|
394
435
|
*Rafael Mendonça França*
|
395
436
|
|
396
|
-
* Remove deprecated `ActiveRecord::Migration.check_pending
|
437
|
+
* Remove deprecated `ActiveRecord::Migration.check_pending!` method.
|
397
438
|
|
398
439
|
*Rafael Mendonça França*
|
399
440
|
|
@@ -50,11 +50,11 @@ module ActiveRecord
|
|
50
50
|
# Implements the ids reader method, e.g. foo.item_ids for Foo.has_many :items
|
51
51
|
def ids_reader
|
52
52
|
if loaded?
|
53
|
-
target.pluck(reflection.association_primary_key)
|
53
|
+
target.pluck(*reflection.association_primary_key)
|
54
54
|
elsif !target.empty?
|
55
|
-
load_target.pluck(reflection.association_primary_key)
|
55
|
+
load_target.pluck(*reflection.association_primary_key)
|
56
56
|
else
|
57
|
-
@association_ids ||= scope.pluck(reflection.association_primary_key)
|
57
|
+
@association_ids ||= scope.pluck(*reflection.association_primary_key)
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
@@ -0,0 +1,265 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
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
|
+
end
|
@@ -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
|
@@ -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
|
@@ -8,11 +8,11 @@ module ActiveRecord
|
|
8
8
|
|
9
9
|
module ClassMethods # :nodoc:
|
10
10
|
private
|
11
|
-
def define_method_attribute(
|
11
|
+
def define_method_attribute(canonical_name, owner:, as: canonical_name)
|
12
12
|
ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
|
13
|
-
owner,
|
13
|
+
owner, canonical_name
|
14
14
|
) do |temp_method_name, attr_name_expr|
|
15
|
-
owner.define_cached_method(
|
15
|
+
owner.define_cached_method(temp_method_name, as: as, namespace: :active_record) do |batch|
|
16
16
|
batch <<
|
17
17
|
"def #{temp_method_name}" <<
|
18
18
|
" _read_attribute(#{attr_name_expr}) { |n| missing_attribute(n, caller) }" <<
|
@@ -12,11 +12,11 @@ module ActiveRecord
|
|
12
12
|
|
13
13
|
module ClassMethods # :nodoc:
|
14
14
|
private
|
15
|
-
def define_method_attribute=(
|
15
|
+
def define_method_attribute=(canonical_name, owner:, as: canonical_name)
|
16
16
|
ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
|
17
|
-
owner,
|
17
|
+
owner, canonical_name, writer: true,
|
18
18
|
) do |temp_method_name, attr_name_expr|
|
19
|
-
owner.define_cached_method("#{
|
19
|
+
owner.define_cached_method(temp_method_name, as: "#{as}=", namespace: :active_record) do |batch|
|
20
20
|
batch <<
|
21
21
|
"def #{temp_method_name}(value)" <<
|
22
22
|
" _write_attribute(#{attr_name_expr}, value)" <<
|