limit the number of objects returned in a has_many
Asked Answered
S

3

11

How can I limit the number of rows returned in a has many relationship? For example:

class User < ActiveRecord::Base
  has_many :photos
end

I want to be able to do:

User.includes(:photos => {:limit => 8}).all

This obviously doesnt work, but something with this functionality. Do I need to write out the SQL myself?

Thanks in advance!

EDIT: I dont want to limit the association, just the query results. So a User might have a thousand photos, I only want the top 3 returned.

Stipendiary answered 20/5, 2011 at 18:50 Comment(0)
Z
2

Just add a limit option to the has_many association:

class User < ActiveRecord::Base
  has_many :photos, :limit => 8
end

EDIT

According to your needs:

class User < ActiveRecord::Base
  has_many :all_photos, :class_name => "Photo"
  has_many :photos, :limit => 8
end

note: changed 'class' to 'class_name' in the all_photos association

Zinkenite answered 20/5, 2011 at 18:53 Comment(4)
It DOES limit the rows returned. However you could just select the 8 top results from the has_many association -> "@user.photos[0..7]"Zinkenite
I want to be able to do this using eager loading, that way I can pull up the top 1000 records with only the first 3 associations in each model...Stipendiary
So you should create two associations. One for the whole collection and an other one for a limited collection. I edited my answer.Zinkenite
This doesn't work with eager loading, see https://mcmap.net/q/737165/-rails-3-limiting-included-objectsDentate
A
12

You don't have to hard code the limit in the model. You can call @user.photos.limit(8). You can also call @user.photos.scoped to get a scope object that does lazy loading. The thing returned from @user.photos may look very, very much like an Array, but it's not - it lies to you!

See http://apidock.com/rails/ActiveRecord/Associations/CollectionProxy for an interesting trip into the rabbit hole - the thing you get back is delegating pretty much all of the standard object inspection calls (class, singleton_class, methods, method, etc.) to an Array object, but it's delegating a certain set of calls to an ActiveRecord::Associations::* object. That's why if you call @user.photos.method(:<<) it will tell you it's using #<Method: Array#<<>, but it's not actually using that - it's using the one in ActiveRecord::Associations::CollectionProxy!

Aubert answered 16/11, 2012 at 23:12 Comment(0)
P
2

You can put a :limit on the actual has_many declaration.

class User < ActiveRecord::Base
  has_many :photos, :limit => 8
end
Pedersen answered 20/5, 2011 at 18:52 Comment(1)
How do I do this on a per query basis instead of on the model?Stipendiary
Z
2

Just add a limit option to the has_many association:

class User < ActiveRecord::Base
  has_many :photos, :limit => 8
end

EDIT

According to your needs:

class User < ActiveRecord::Base
  has_many :all_photos, :class_name => "Photo"
  has_many :photos, :limit => 8
end

note: changed 'class' to 'class_name' in the all_photos association

Zinkenite answered 20/5, 2011 at 18:53 Comment(4)
It DOES limit the rows returned. However you could just select the 8 top results from the has_many association -> "@user.photos[0..7]"Zinkenite
I want to be able to do this using eager loading, that way I can pull up the top 1000 records with only the first 3 associations in each model...Stipendiary
So you should create two associations. One for the whole collection and an other one for a limited collection. I edited my answer.Zinkenite
This doesn't work with eager loading, see https://mcmap.net/q/737165/-rails-3-limiting-included-objectsDentate

© 2022 - 2024 — McMap. All rights reserved.