Reputation: 1269
In my Rails 4 application I have a many-to-many relationship between Blogs and Categories with a has_many :through => join table.
I'm using the gem will_paginate to paginate pages of blog posts.
However for each page, I'd like to show the unique categories that are related to every single blog post being shown per page. Currently I have a query like:
Category.joins(:blogs).paginate(page: params[:page], per_page: 20).uniq
This works great for the first page, yet for the second when params[:page] == 2, the result is an empty set of categories even though this second page contains blog posts with categories.
How can I fix this?
EDIT:
action:
def home
@categories = Category.joins(:blogs).paginate(page: params[:page], per_page: 20).uniq
@blogs = Blog.paginate(page: params[:page], per_page: 20)
respond_to do |format|
format.html
end
end
partial to display categories:
<ul class="filter">
<li><a class="active" href="" data-filter="*">All</a></li>
<% @categories.each do |category| %>
<li><a href="#" data-filter=".<%= category.title.downcase unless nil %>"><%= category.title unless nil %></a></li>
<% end %>
</ul>
The partial logic is less relevant here compared to the collection of blogs and categories being populated in the action.
Upvotes: 0
Views: 1633
Reputation: 117427
If your database supports it, one option is to use a subquery. So:
Category
.all
.select("categories.*, (select count(blogs.id) from blogs where blogs.category_id = categories.id) as number_of_blogs")
.paginate(page: params[:page], per_page: 20)
Upvotes: 0
Reputation: 5229
If I understand the question: You are trying to show the blogs with its categories without duplication.
Then you can do this way:
blogs = Blog.includes(:categories).paginate(page: params[:page], per_page: 20)
There no reason for show a category more than 1 time, unless you duplicated the relation, but you must prevent that.
If you do:
@categories = Category.joins(:blogs).paginate(page: params[:page], per_page: 20)
you got up to 20 records of categories. Each of them, with all its blogs.
You must not do this: @blogs = Blog.paginate(page: params[:page], per_page: 20)
, because you can't paginate with the same params[:page]
as @categories, and you have the blogs data attached to each category.
With only the @categoríes setted you can do at your view:
<% @categories.each do |category| %>
<%= "#{category.name} has #{category.blogs.size} blogs" %>
<% category.blogs.each do |blog|>
<%= blog.author %>
<% end %>
<% end %>
And you don't need the instance variable @blogs at all.
EDIT: Answer revealed through private chat:
categories = []
blogs.each do |b|
categories.push(*b.categories)
end
categories.uniq
Upvotes: 1