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