diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 6258a16d0f6ec1b4a456e19e8b66da9e4671b836..2d0861d5c931e5b8c8ce27bbcefb0d5f4dfdac4d 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -408,7 +408,17 @@ def scope_for_create end def eager_loading? - @should_eager_load ||= (@eager_load_values.any? || (@includes_values.any? && references_eager_loaded_tables?)) + @should_eager_load ||= + @eager_load_values.any? || + @includes_values.any? && (joined_includes_values.any? || references_eager_loaded_tables?) + end + + # Joins that are also marked for preloading. In which case we should just eager load them. + # Note that this is a naive implementation because we could have strings and symbols which + # represent the same association, but that aren't matched by this. Also, we could have + # nested hashes which partially match, e.g. { :a => :b } & { :a => [:b, :c] } + def joined_includes_values + @includes_values & @joins_values end def ==(other) diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index 325fc58958292c3ea3181fb5eb90175cbcec03c9..f1d061133c552beb746316ccf4d31dfbde8c0973 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -1040,4 +1040,12 @@ def test_preloading_polymorphic_with_custom_foreign_type } assert_no_queries { assert_equal groucho, sponsor.thing } end + + def test_joins_with_includes_should_preload_via_joins + post = assert_queries(1) { Post.includes(:comments).joins(:comments).order('posts.id desc').to_a.first } + + assert_queries(0) do + assert_not_equal 0, post.comments.to_a.count + end + end end