If you have a blog, you are likely going to need to restrict the number of posts you show. This needs to be done to not overwhelm the reader as well as speed up page loading times.

Up until now, we didn't need to have pagination on the Mirror Communications blog, as we only had a few posts to show.

Now that we have more, we thought it was time to implement this feature - but we wanted to use our own custom styles.

Unfortunately, we couldn't find any tutorials online which provided a good overview on how to do accomplish this task. Therefore, we decided to write this post to help anyone else out who might be struggling with this problem.

For reference, here is the standard html markup for our pagination.

HTML


<div class="section-block pagination-3 no-padding-top">
 <div class="row">
	<div class="column width-12">
		<ul>
		 <li><a class="pagination-previous icon-left-open" href="#"><span class="icon-left-open-mini"></span></a></li>
		 <li><a class="current" href="#">1</a></li>
		 <li><a href="#">2</a></li>
		 <li><a href="#">3</a></li>
		 <li><a href="#">4</a></li>
		 <li><a class="pagination-next disabled" href="#"><span class="icon-right-open-mini"></span></a></li>
		</ul>
	</div>
 </div>
</div>


Along with our CSS, the following pagination style will be achieved

Now to actually make this happen using the Kaminari gem!

First of all here is a link to the Kaminari gem on GitHub.

Now let's get started:


 gem 'kaminari'
 bundle install


Posts Controller

Now open your posts controller file or whatever controller you are using to display posts, and add the following: .page(params[:page]).per(9) to your index action. The number nine is simply the number of posts we have chosen to show on a per page basis - you can change this to whatever you would like.

Example:


 def index

  if params[:category].blank?
  @posts=Post.all.order("created_at desc").page(params[:page]).per(9)
  else
  @category_id = Category.find_by(name: params[:category]).id
  @posts = Post.where(category_id: @category_id).order("created_at DESC").page(params[:page]).per(9)
  end

end


Kaminari Views

You will now need to create kaminari views so that you can style the pagination to your specifications. Fortunately, the Kaminari gem provides you with several themes as well as a default style. To view all the different options, please click here.

The default views for Kaminari place all the code inside span tags instead of li tags, thus we decided to use the bootstrap template and customize it from there.


 rails g kaminari:views bootstrap3


This will create several new view files under the Kaminari folder. Navigate to this folder and open the first file, which is _first_page.html.erb. As you can see from the code below, we added a class for the icon and its direction.


 <li>
  <%= link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, :remote => remote, class: "icon-left-open-mini pagination-previous icon-left-open" %>
</li>


The second file _gap.html.erb was left alone.

_last_page.html.erb

For the last page we again added a class, this time for the icon which points right:


 <li class="">
  <%= link_to_unless current_page.last?, raw(t 'views.pagination.last'), url, {:remote => remote, class: "pagination-next icon-right-open-mini"} %>
</li>


For _next_page.html.erb, we deleted all of the content inside the file, as we didn't want to include this on our blog page.

_page.html.erb

This partial is basically for the active page, so this is where we added a current class that highlights the page number.


<% if page.current? %>
  <li>
    <%= content_tag :a, page, remote: remote, rel: (page.next? ? 'next' : (page.prev? ? 'prev' : nil)), class: "current" %>
  </li>
<% else %>
  <li>
    <%= link_to page, url, remote: remote, rel: (page.next? ? 'next' : (page.prev? ? 'prev' : nil)) %>
  </li>
<% end %>


_paginator.html.erb

This template is where we added our div classes, as shown in the html version above:


<%= paginator.render do -%>
  <div class="section-block pagination-3 no-padding-top"><!-- Added Here -->
    <div class="row"><!-- Added Here -->
      <div class="column width-12"><!-- Added Here -->
        <ul>
          <%= first_page_tag unless current_page.first? %>
          <%= prev_page_tag unless current_page.first? %>
          <% each_page do |page| -%>
            <% if page.left_outer? || page.right_outer? || page.inside_window? -%>
              <%= page_tag page %>
            <% elsif !page.was_truncated? -%>
              <%= gap_tag %>
            <% end -%>
          <% end -%>
          <%= next_page_tag unless current_page.last? %>
          <%= last_page_tag unless current_page.last? %>
        </ul>
      </div><!-- Added Here -->
    </div><!-- Added Here -->
  </div><!-- Added Here -->
<% end -%>


Finally, for the last partial: _pre_page.html.erb, we just added a class declaration:


<li>
  <%= link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, :rel => 'prev', :remote => remote, class: "icon-left-open-mini pagination-previous icon-left-open" %>
</li>


One last thing!

You may run into an issue, where you are unable to remove the default styling. This happened to us, as we wanted to remove the "previous" and "next" text. To remove the un-wanted text and icons, open config/locales/en.yml and follow the example listed below:


en:
  views:
    pagination:
      next: ""
      previous: ""
      first: ""
      last: ""


Here is a link to the Kaminari wiki where this solution was posted.

Final Step...

Add the pagination call to your index.html.erb file:


 <%= paginate @posts %>


I hope this post is helpful :).

Cheers, Brian