From c840b18ac31a852d99ff760229f2c087b6961727 Mon Sep 17 00:00:00 2001
From: Sammy Larbi <sam@codeodor.com>
Date: Sat, 3 Jan 2015 13:30:30 -0600
Subject: Fix n+1 query problem when eager loading nil associations (fixes
 #18312)

---
 activerecord/CHANGELOG.md                                      | 4 ++++
 activerecord/lib/active_record/associations/join_dependency.rb | 7 ++++++-
 activerecord/test/cases/associations/eager_test.rb             | 8 ++++++++
 3 files changed, 18 insertions(+), 1 deletion(-)

(limited to 'activerecord')

diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 8980a1d874..dfcf4b92ac 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,7 @@
+*   Fix n+1 query problem when eager loading nil associations (fixes #18312)
+
+    *Sammy Larbi*
+
 *   Clear query cache on rollback.
 
     *Florian Weingarten*
diff --git a/activerecord/lib/active_record/associations/join_dependency.rb b/activerecord/lib/active_record/associations/join_dependency.rb
index 4b75370171..fcf06323e6 100644
--- a/activerecord/lib/active_record/associations/join_dependency.rb
+++ b/activerecord/lib/active_record/associations/join_dependency.rb
@@ -232,6 +232,7 @@ module ActiveRecord
       end
 
       def construct(ar_parent, parent, row, rs, seen, model_cache, aliases)
+        return if ar_parent.nil?
         primary_id  = ar_parent.id
 
         parent.children.each do |node|
@@ -248,7 +249,11 @@ module ActiveRecord
 
           key = aliases.column_alias(node, node.primary_key)
           id = row[key]
-          next if id.nil?
+          if id.nil?
+            nil_association = ar_parent.association(node.reflection.name)
+            nil_association.loaded!
+            next
+          end
 
           model = seen[parent.base_klass][primary_id][node.base_klass][id]
 
diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb
index fdb437d11d..1d00177405 100644
--- a/activerecord/test/cases/associations/eager_test.rb
+++ b/activerecord/test/cases/associations/eager_test.rb
@@ -77,9 +77,17 @@ class EagerAssociationTest < ActiveRecord::TestCase
 
   def test_has_many_through_with_order
     authors = Author.includes(:favorite_authors).to_a
+    assert authors.count > 0
     assert_no_queries { authors.map(&:favorite_authors) }
   end
 
+  def test_eager_loaded_has_one_association_with_references_does_not_run_additional_queries
+    Post.update_all(author_id: nil)
+    authors = Author.includes(:post).references(:post).to_a
+    assert authors.count > 0
+    assert_no_queries { authors.map(&:post) }
+  end
+
   def test_with_two_tables_in_from_without_getting_double_quoted
     posts = Post.select("posts.*").from("authors, posts").eager_load(:comments).where("posts.author_id = authors.id").order("posts.id").to_a
     assert_equal 2, posts.first.comments.size
-- 
cgit v1.2.3