Skip to content

Commit c6b227b

Browse files
authored
Merge pull request rails#46605 from ghiculescu/compute_class_error
More detailed error message for `compute_class` errors
2 parents ea2e3cc + 04ecf98 commit c6b227b

File tree

4 files changed

+57
-16
lines changed

4 files changed

+57
-16
lines changed

activerecord/lib/active_record/reflection.rb

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -423,22 +423,16 @@ def compute_class(name)
423423
raise ArgumentError, "Polymorphic associations do not support computing the class."
424424
end
425425

426-
msg = <<-MSG.squish
427-
Rails couldn't find a valid model for #{name} association.
428-
Please provide the :class_name option on the association declaration.
429-
If :class_name is already provided, make sure it's an ActiveRecord::Base subclass.
430-
MSG
431-
432426
begin
433427
klass = active_record.send(:compute_type, name)
434428

435429
unless klass < ActiveRecord::Base
436-
raise ArgumentError, msg
430+
raise ArgumentError, compute_class_error_message(klass)
437431
end
438432

439433
klass
440434
rescue NameError
441-
raise NameError, msg
435+
raise ArgumentError, compute_class_error_message
442436
end
443437
end
444438

@@ -605,6 +599,16 @@ def extensions
605599
end
606600

607601
private
602+
def compute_class_error_message(klass = nil)
603+
msg = +"Rails couldn't find a valid model for the #{name} association. "
604+
if !options[:class_name]
605+
msg << "Use the :class_name option on the association declaration to tell Rails which model to use."
606+
else
607+
msg << "Ensure the class provided to :class_name exists and is an ActiveRecord::Base subclass."
608+
end
609+
msg
610+
end
611+
608612
# Attempts to find the inverse association name automatically.
609613
# If it cannot find a suitable inverse association name, it returns
610614
# +nil+.

activerecord/test/cases/associations_test.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -417,15 +417,15 @@ class ModelAssociatedToClassesThatDoNotExist < ActiveRecord::Base
417417
end
418418

419419
def test_associations_raise_with_name_error_if_associated_to_classes_that_do_not_exist
420-
assert_raises NameError do
420+
assert_raises ArgumentError do
421421
ModelAssociatedToClassesThatDoNotExist.new.non_existent_has_one_class
422422
end
423423

424-
assert_raises NameError do
424+
assert_raises ArgumentError do
425425
ModelAssociatedToClassesThatDoNotExist.new.non_existent_belongs_to_class
426426
end
427427

428-
assert_raises NameError do
428+
assert_raises ArgumentError do
429429
ModelAssociatedToClassesThatDoNotExist.new.non_existent_has_many_classes
430430
end
431431
end

activerecord/test/cases/reflection_test.rb

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,16 +138,51 @@ def test_irregular_reflection_class_name
138138
assert_equal "PluralIrregular", reflection.class_name
139139
end
140140

141-
def test_reflection_klass_is_not_ar_subclass
142-
[:account_invalid,
143-
:account_class_name,
141+
def test_reflection_klass_not_found_with_no_class_name_option
142+
[:account_invalid_no_class_name_option,
144143
:info_invalids,
144+
].each do |rel|
145+
expected = <<-MSG.squish
146+
Rails couldn't find a valid model for the #{rel} association.
147+
Use the :class_name option on the association declaration to tell Rails which model to use.
148+
MSG
149+
150+
err = assert_raise(ArgumentError) do
151+
UserWithInvalidRelation.reflect_on_association(rel).klass
152+
end
153+
154+
assert_includes err.message, expected
155+
end
156+
end
157+
158+
def test_reflection_klass_not_found_with_pointer_to_non_existent_class_name
159+
expected = <<-MSG.squish
160+
Rails couldn't find a valid model for the class_name_provided_not_a_class association.
161+
Ensure the class provided to :class_name exists and is an ActiveRecord::Base subclass.
162+
MSG
163+
164+
err = assert_raise(ArgumentError) do
165+
UserWithInvalidRelation.reflect_on_association(:class_name_provided_not_a_class).klass
166+
end
167+
168+
assert_includes err.message, expected
169+
end
170+
171+
def test_reflection_klass_requires_ar_subclass
172+
[:account_class_name,
145173
:infos_class_name,
146174
:infos_through_class_name,
147175
].each do |rel|
148-
assert_raise(ArgumentError) do
176+
expected = <<-MSG.squish
177+
Rails couldn't find a valid model for the #{rel} association.
178+
Ensure the class provided to :class_name exists and is an ActiveRecord::Base subclass.
179+
MSG
180+
181+
err = assert_raise(ArgumentError) do
149182
UserWithInvalidRelation.reflect_on_association(rel).klass
150183
end
184+
185+
assert_includes err.message, expected
151186
end
152187
end
153188

activerecord/test/models/user_with_invalid_relation.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
# frozen_string_literal: true
22

33
class UserWithInvalidRelation < ActiveRecord::Base
4-
has_one :account_invalid
4+
has_one :account_invalid_no_class_name_option
55

66
has_one :account_class_name, class_name: "AccountInvalid"
77

8+
has_one :class_name_provided_not_a_class, class_name: "NotAClass"
9+
810
has_many :user_info_invalid
911
has_many :info_invalids, through: :user_info_invalid
1012

0 commit comments

Comments
 (0)