Reputation: 4464
I have this association
class Product
has_many :categorizations
has_many :categories, through: :categorization
scope :first_five, lambda { limit(5) }
end
class Category
has_many :categorizations
has_many :products, through: :categorization
end
For each category, I want to get first five products using first_five
scope defined above.
To minimize DB request, I use includes()
@categories = Category.includes(:products).all
But how do you add the scope to products
? I don't want to use default_scope
since it affects everything.
I can't find it on Google (or I just can't get the right search term for it)
Thanks
Upvotes: 2
Views: 249
Reputation: 38645
The new syntax for lambda scope in Rails 4 is:
scope :first_five, -> { limit(5) }
To limit to five products in your AR query, you could do:
@categories = Category.includes(:products).merge(Product.first_five).all
The merge(Product.first_five)
is going to add a left outer join
on the limited five products.
Update:
The above code as commented is going to limit the categories. A possible solution to your original problem could be to add another has_many...through
relation calling it limited_products
on the Category
model as:
has_many :limited_products, -> { limit(5) },
through: :products,
source: :categorizations
With this Categeory.includes(:limited_products)
should yield the expected result of limiting products to 5
.
As you've suggested, add the source: :categorizations
option to the newly added association limited_products
. source
and class_name
should have been synonymous. Since the association we are defining is a has_many...through
association which ignores class_name
option, we should be using :source
option instead of :class_name
option. Other association options ignored in a has_many...through
relation are :primary_key
and :foreign_key
.
Upvotes: 2
Reputation: 5734
@categories = Category.includes(:products).all
It will fetch all the categories and its related products. Here limit does not work for products.
Just an alternative way.
In the Category
model
has_many :products, through: :categorization, limit: 5
Now you need to make joins onto it, like the following.
@categories = Category.joins(:products).all
It returns all the category and upon taking each category.products, it will return five products for each category.
I know it is not the answer that you are looking for. But that what I have.
Alternative Way
In the Category model
has_many :products, through: :categorization
def get_products(limit=5)
products[0...limit]
end
And in the controller
@categories = Category.joins(:products).all
@categories.each do |category|
products = category.get_products
# YOUR CODE GOES HERE
end
You will get 5 products for each category.
Upvotes: 2
Reputation: 8058
This will work
class Category
has_many :categorizations
has_many :products, -> { limit(5) }, through: :categorization
end
Upvotes: 1