From fbbbfa84dbb78dc436ffaea3d8ca69f5b6e371b2 Mon Sep 17 00:00:00 2001 From: ykpythemind Date: Sun, 26 Dec 2021 14:55:06 +0900 Subject: [PATCH] Better error messages when association name is invalid in the argument of `ActiveRecord::QueryMethods::WhereChain#missing` before: ``` Post.where.missing(:cars).to_a # Post does not have association named `cars` => NoMethodError: undefined method `table_name' for nil:NilClass ``` It is complicated message. after: ``` Post.where.missing(:cars).to_a => ArgumentError: An association named `:cars` does not exist on the model `Post`. ``` --- activerecord/lib/active_record/relation/query_methods.rb | 3 +++ activerecord/test/cases/relation/where_chain_test.rb | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 3def087ef3..ad67c01231 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -97,6 +97,9 @@ module ActiveRecord def missing(*associations) associations.each do |association| reflection = @scope.klass._reflect_on_association(association) + unless reflection + raise ArgumentError.new("An association named `:#{association}` does not exist on the model `#{@scope.name}`.") + end @scope.left_outer_joins!(association) @scope.where!(reflection.table_name => { reflection.association_primary_key => nil }) end diff --git a/activerecord/test/cases/relation/where_chain_test.rb b/activerecord/test/cases/relation/where_chain_test.rb index eb2fc72cc0..37dfcb28c3 100644 --- a/activerecord/test/cases/relation/where_chain_test.rb +++ b/activerecord/test/cases/relation/where_chain_test.rb @@ -33,6 +33,14 @@ module ActiveRecord assert_equal [posts(:authorless)], Post.where.missing(:author).to_a end + def test_missing_with_invalid_association_name + e = assert_raises(ArgumentError) do + Post.where.missing(:cars).to_a + end + + assert_match(/An association named `:cars` does not exist on the model `Post`\./, e.message) + end + def test_missing_with_multiple_association assert posts(:authorless).comments.empty? assert_equal [posts(:authorless)], Post.where.missing(:author, :comments).to_a