#505 √ wontfix
jodosha

Eager loading doesn't respect :limit option of the loaded association

Reported by jodosha | June 28th, 2008 @ 10:43 AM | in 2.x

@@@ruby class Category < ActiveRecord::Base has_and_belongs_to_many :movies has_and_belongs_to_many :most_recent_movies, :class_name => 'Movie', :order => 'created_at DESC', :limit => 10 end

class Movie < ActiveRecord::Base has_and_belongs_to_many :categories end

Category.find(1).most_recent_movies # => returns 10 movies Category.find(1, :include => :most_recent_movies).most_recent_movies # => returns all the associated movies



I attached a patch to solve this issue.

Comments and changes to this ticket

  • Andrew White

    Andrew White June 28th, 2008 @ 03:50 PM

    On the surface this appears to fix things but what you have to remember is that the eager loading may be for more than one parent so if you just limit the query the result will be incorrect unless the associated records are the same for each parent.

    For example if you do a Category.find(:all, :include => :most_recent_movies) then limiting the query will not give you want you want. The only way to fix it is to discard any extra records after they have been preloaded.

    However in your example there may be irregular distribution of movies between categories so I wouldn't recommend eager loading - you may end up loading all of the movie records just to fill the sparser categories.

    The best way to proceed I think would be to patch the preloading code so that extra records are discarded and add a warning in the documentation for eager loading of limited associations.

  • Frederick Cheung

    Frederick Cheung June 28th, 2008 @ 04:29 PM

    Eager loading and limits on the association don't really match. As Andrew says, your patch will break most of the time when you're loading (in your example) more than one category.

    Limiting after load is a bit messy (and sort of creates the illusion that we can eager load such associations efficiently). We already do that for has_one though. If you do go down that road, add_preloaded_records_to_collection is probably the place to enforce that.

  • MatthewRudy

    MatthewRudy June 29th, 2008 @ 01:21 AM

    and then one could argue the following;

    class A
      has_many :bs, :limit => 2
    end
    
    >> a.bs
    => [#< B:1 >, #<B:2 >]
    >> a.bs.create()
    (irb):10:in `irb_binding': limit of association :bs exceeded (HasManyLimitException)
    
    or
    
    >> a.bs.create()
    => #< B:new >
    >> a.bs
    => [#< B:2 >, #< B:new >]
    

    but then which object do you push off...

    and what if you actually wanted to maintain a limit, but allowed a create, so it'd be a hard remove of one of them...

    I dunno...

    just drunkenly (without drinking anything 'cept tea) imagining the craziness that could be involved!

  • Pratik

    Pratik July 12th, 2008 @ 02:22 PM

    • → State changed from “new” to “wontfix”

    What everyone else said.

  • jodosha

    jodosha July 12th, 2008 @ 02:37 PM

    I tried to figure out how to fix it, but an unnecessary complexity would be added to the code.

    I agree to wontfix status.

    It would be nice to specify this behavior into the documentation, in order to avoid unexpected results.

  • Pratik

    Pratik July 12th, 2008 @ 02:52 PM

    Hey jodosha,

    If you message me (lifo) at github, I'll add you to docrails. So that you can commit the docpatch yourself anytime you wish.

    Thanks.

  • jodosha

    jodosha November 3rd, 2008 @ 09:19 AM

    This is just a reminder: the case was documented in http://github.com/lifo/docrails/...

Please Login or create a free account to add a new comment.

You can update this ticket by sending an email to from your email client. (help)

Create your profile

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

Source available from github

The Git repository resides at http://github.com/rails

Check out the current development trunk (Edge Rails) with:

git clone git://github.com/rails/rails.git

Creating or reviewing a patch

See the contributor guide.

Creating a feature request

Please don't. If you want a new feature in Rails, you'll have to pull up your sleeves and get busy yourself. Or convince someone else to do it. See the contributor guide on how to get going. But posting them here is just going to lead to ticket root.

Creating a bug report

When creating a bug report, be sure to include as much relevant information as possible. Post the code sample that causes the problem. Preferably, alter the unit tests and show through either changed or added tests how the expected behavior is not occuring.

Security vulnerabilities should be reported via an email to security@rubyonrails.org, do not use trac for reporting security vulnerabilities. All content in trac is publicly available as soon as it is posted.

Then don't get your hopes up. Unless you have a "Code Red, Mission Critical, The World is Coming to an End" kinda bug, you're creating this ticket in the hope that others with the same problem will be able to collaborate with you on solving it. Do not expect that the ticket automatically will see any activity or that others will jump to fix it. Creating a ticket like this is mostly to help yourself start on the path of fixing the problem and for others to sign on to with a "I'm having this problem too".

Shared Ticket Bins