Skip to content

Commit 827f4ef

Browse files
authored
Merge pull request rails#52059 from fatkodima/move-associations-errors-to-errors
Explicitly load Active Record associations related errors
2 parents 00f3856 + 08bee53 commit 827f4ef

File tree

3 files changed

+267
-262
lines changed

3 files changed

+267
-262
lines changed

activerecord/lib/active_record/associations.rb

Lines changed: 0 additions & 262 deletions
Original file line numberDiff line numberDiff line change
@@ -1,268 +1,6 @@
11
# frozen_string_literal: true
22

33
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-
2664
# See ActiveRecord::Associations::ClassMethods for documentation.
2675
module Associations # :nodoc:
2686
extend ActiveSupport::Autoload

0 commit comments

Comments
 (0)