This project is archived and is in readonly mode.

#1770 ✓stale
Jonathan Garvin

Backtracking association proxy chained methods

Reported by Jonathan Garvin | January 16th, 2009 @ 06:58 AM | in 3.x

Bear with me, this is hard to explain, but I have a failing test case attached that demonstrates the problem (hopefully clearly enough)

When chaining association proxy methods together in such a way that you scope to a has_many, then follow a different belongs_to, and they turn around and come back on the has_many on the other side, you'll get different results depending on if you wrap part of of the query in a class method.

So, in the attached test, I start at authors(:david). David has_many categorizations. Each categorization belongs_to a category. And each category has many categorizations, some of which do not belong to David. I'm trying to find which of David's categorizations have siblings that may not belong to David.

The first way I check is to call... count_without_class_method = authors(:david).categorizations.find(:all).select {|cz| cz.category.categorizations.size > 1 }.size (The find(:all) is unnecessary, but included to make both samples as identical as possible)

For the second sample, I put everything everthing from find(:all) up to .size into a class method on Categorization, so that I can call... count_with_class_method = authors(:david).categorizations.that_have_siblings_with_common_category_parent.size

In theory, these two lines are both doing the exact same thing and should return the same result. However, the last line in the test fails because count_without_class_method != count_with_class_method

Comments and changes to this ticket

  • Diego Algorta

    Diego Algorta February 17th, 2009 @ 06:37 PM

    Maybe you'd like to test if the patch in #1960 fixes this problem? Haven't had the time to test your diff there.

  • Jonathan Garvin

    Jonathan Garvin February 18th, 2009 @ 02:30 AM

    Thanks for the suggestion Diego, but when I apply your patch, my test attached above still fails, and a new test fails ( test_named_scope(DefaultScopingTest) ).

    I don't think the issue I'm dealing with has is specific to named scopes but instead to associations proxies in general.

  • Ryan Berdeen

    Ryan Berdeen February 18th, 2009 @ 07:00 AM

    In fact, the same problem occurs with named scopes and class methods, but it's the basically the inverse of #1960 (I thought they were dups at first, sorry for the confusion). Class methods called through association proxies and named scopes are both evaluated within the context of a with_scope. Adding

    
    named_scope :having_author_id, lambda { |author_id| {:conditions => ['`categorizations`.author_id = ?', author_id]} }
    

    to Categorization and then doing

    
    count_without_class_method = authors(:david).categorizations.find(:all).select {|cz| cz.category.categorizations.size > 1 }.size
        count_with_class_method = Categorization.having_author_id(authors(:david).id).that_have_siblings_with_common_category_parent.size
        assert_equal(count_without_class_method,count_with_class_method)
    

    gives the same result as accessing it through the association_collection.

    Either way, to get the result you want, just put the cz.category.categorizations.size within an exclusive scope:

    
    def that_have_siblings_with_common_category_parent
      find(:all).select {|cz| with_exclusive_scope {cz.category.categorizations.size > 1} }
    end
    
    With this, the test passes.
    
  • Jonathan Garvin

    Jonathan Garvin February 18th, 2009 @ 07:46 AM

    Thanks Ryan, that's good to know. But I wonder if that should be considered the "correct" way to do that, or is that a hack/workaround/band-aid? I'm inclined to think it's a hack and we'd be better off solving the underlying problem (though, I don't know what that would be, yet). However, I'd rather be proven wrong before I waste any time trying to "fix" something that nobody else wants fixed. ;-)

  • Jeremy Kemper

    Jeremy Kemper May 4th, 2010 @ 06:48 PM

    • Milestone changed from 2.x to 3.x
  • Santiago Pastorino

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

    • State changed from “new” to “open”
    • Importance changed from “” to “”

    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:42 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="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Attachments

Referenced by

Pages