Reputation: 7108
I'm using Rails 4.2. I have 3 tables like this:
class Collection < ActiveRecord::Base
has_many :shares
has_many :images, through: :shares
has_many :latest_images, -> { order(created_at: :desc).limit(10) }, class_name: 'Image', through: :shares, source: :image
end
class Share < ActiveRecord::Base
belongs_to :image
belongs_to :collection
end
class Image < ActiveRecord::Base
has_many :shares
has_many :collections, through: :shares
end
My goal is to select some collections and preload the first 10 newest cards of each collection using the latest_images
relation.
If I do simply:
collections = Collection.where(some_condition).includes(:latest_images)
The problem is latest_images will contain all cards, not only the last 10 (even if there's a limit(10)
)
collections.first.latest_images.count # => more than 10!!!
Instead, if I add the limit(10)
after loading the collections, I'll have a N+1 query problem:
collections.each { |collection| collection.latest_images.limit(10).do_something } # N+1 QUERY
Any solution?
Upvotes: 7
Views: 4962
Reputation: 34784
There is a note tucked away in the associations documentation under "Eager loading of associations":
If you eager load an association with a specified :limit option, it will be ignored, returning all the associated objects.
So, it is behaving as documented even though that might not be the intuitive behaviour.
The work around is to not eager load the limited associated and to access separately afterwards. As you point out that's not ideal but it is almost certainly preferable to loading all of the associated objects without a limit.
Upvotes: 8