Rails: `includes the` has_many` relation with `limit`

I am using Rails 4.2. I have 3 tables:

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 latest maps of each collection using the latest_images relation.

If I just:

 collections = Collection.where(some_condition).includes(:latest_images) 

Problem: last_images will contain all the cards, not just the last 10 (even if there is limit(10) )

 collections.first.latest_images.count # => more than 10!!! 

Instead, if I add limit(10) after loading the collections, I will have a problem with requesting N + 1:

 collections.each { |collection| collection.latest_images.limit(10).do_something } # N+1 QUERY 

Any solution?

+6
source share
1 answer

The documentation for associations contains a note in the "Unwanted Download of Associations" section:

If you want to load a link with the specified limit parameter, it will be ignored, returning all related objects.

So, it behaves as documented, although it may not be an intuitive behavior.

The work around is not to download the limited connection and access to it separately. Since you are specifying that this is not ideal, it is almost certainly advisable to download all related objects without restriction.

+3
source

All Articles