This project is archived and is in readonly mode.

#4831 ✓stale
Jason Frey

Eager Loading a HABTM with further includes does not properly load when duplicates are in the HABTM

Reported by Jason Frey | June 11th, 2010 @ 06:12 PM

When eager loading a HABTM and also including anything beyond it, duplicate objects in the HABTM only load the first object's further includes, but the further includes are not loaded for subsequent objects. It's hard to explain succinctly, so here's an example (with a test down further down):

Post has_and_belongs_to_many Categories and Categories has_many Categorizations.
Post 1 has categories 1 and 3.
Post 2 has category 1.
Calling Post.find(:all, :include => {:category => :categorizations}) will cause the categorizations to be loaded for the category objects tied to Post 1, however the category object for Post 2 will not have the categorizations loaded. Subsequent calls to it will show database queries executing.

From what I can tell...In preload_associations, after the first level :category include is handled, it passes an array of categories [1, 3, 1] to the next level of preload_associations for the :categorizations. preload_associations calls uniq right at the start on the records passed in. The uniq ends up changing it to [1, 3], and that is how the duplicates are lost. If I remove the uniq call, the test below passes, however then it breaks test_including_duplicate_objects_from_belongs_to. Since that uniq call is in AR 2.2+, I am assuming this will happen on all versions including 3.

Add the following test to cases\associations\eager_test.rb, and also add a require for 'models\categorization' and the fixture for :categorizations (patch attached, but it's against 2.2.2).

  def test_deep_including_through_habtm
    posts = Post.find(:all, :include => {:categories => :categorizations}, :order => "")
    assert_no_queries { assert_equal 2, posts[0].categories[0].categorizations.size }
    assert_no_queries { assert_equal 0, posts[0].categories[1].categorizations.size }
    assert_no_queries { assert_equal 2, posts[1].categories[0].categorizations.size }

The third assert_no_queries will fail. If you change the very first line of preload_associations to remove the uniq, the test will pass, however test_including_duplicate_objects_from_belongs_to will fail. For now, that's the only way I could get the test to pass.

Comments and changes to this ticket

  • Santiago Pastorino

    Santiago Pastorino February 2nd, 2011 @ 04:37 PM

    • State changed from “new” to “open”

    This issue has been automatically marked as stale because it has not been commented on for at least three months.

    The resources of the Rails core team are limited, and so we are asking for your help. If you can still reproduce this error on the 3-0-stable branch or on master, please reply with all of the information you have about it and add "[state:open]" to your comment. This will reopen the ticket for review. Likewise, if you feel that this is a very important feature for Rails to include, please reply with your explanation so we can consider it.

    Thank you for all your contributions, and we hope you will understand this step to focus our efforts where they are most helpful.

  • Santiago Pastorino

    Santiago Pastorino February 2nd, 2011 @ 04:37 PM

    • State changed from “open” to “stale”

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href=""></a>

People watching this ticket