Rails

Using Kaminari


Hello there,

Today I’d like to talk about pagination in Rails. When I started to learn RoR I did a simple application that included some products "to sell", with description, stock, price, an image of the product, etc. You could add, delete, edit and all this kind of things that we always have in this type of applications.

One of the problems that I found doing that was that if I added several different products I could get a very large list of items and see them in a scroll down list, but that was a bit tedious >.<!

After a while I was able to find a solution to the problem, and that’s what I want to show you now, how to use "kaminari".

Kaminari gives us an easy way of pagination; first you have to add it into the Gemfile.

gem 'kaminari'

Then run bundle to install it.

$ bundle

Kaminari uses a scope page for an ActiveRecord model. For example, if you have 50 items and then write this:

Product.page(5)

… you are getting nothing. Using page you can decide in what page you are going to be located in your application. Default per_page is 25 so, in this case we are trying to be in page 5, but since we only have 50 items we need to add 75 more because 125 items is the minimum amount for this. You can change this value using the per scope. Look at this example:

Product.page(4).per(2)

Which means that if you have a list with 10 items you are going to have as a result 5 pages with 2 items per page, and you are going to be located in the 4th page, but you are not going to be able to navigate to other pages because we are selecting page 4 by default. You can see what I mean here:

image alt

Fixing that, you have to modify your controller, in my case that is "products_controller.rb". I used the index action and the :page parameter to navigate in all the pages.

def index
   @products = Product.order("description").page(params[:page]).per(2)
end

We need to modify our template to use the helper method called paginate and we have to transfer the list of products that we want to paginate. So, we have:

products/index.html.erb

<H1><% title "Products" %></H1>
<table>
  <tr>
    <th>Image url</th>
    <th>Title</th>
    <th>Description</th>
    <th>Price</th>
    <th>Buy</th>
  </tr>

<%= paginate @products %>
<div id="products">
    <%= render @products %>
</div>
</table>
<p>
  Item Count: <%= @order.order_items.count %>
</p>
<p><%= link_to "Create a New Product", new_product_path, :id => "new_product" %></p>

products/_product.html.erb

<tr>
  <td><%= image_tag "/images/products/#{product.image_url}" %><td>
  <td><%= product.title %><%= product.description %></td>
  <td><%= print_price(product.price) %></td>
  <td><%= raw(print_stock(product.stock)) %></td>
  <td><%= button_to "Add to Cart", order_items_path(:product_id => product.id) %></td>
  <td><%= link_to 'Show', product %></td>
  <td><%= link_to 'Edit', edit_product_path(product) %></td>
  <td><%= link_to 'Destroy', product, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>

To navigate between the pages we have "Prev" and "Next" by default, as you can see in the first image. You can change these words adding the next code in config/locales/en.yml

en:
  hello: "Hello world"
  views:
    pagination:
      previous: "&lt; Previous Previous"
      next: "Next Next &gt;"
      truncate: "..."

Now you will see the changes:

image alt

We can use kaminari for any ActiveRecord queries and it's very easy. You need to use the scope per after page and it will work like a charm.

This is a simple example to understand how to use kaminari. I hope it is useful to you.

You can find more information here.

Sources:

Stay tuned,

E.

Beginner
Fixing Rspec and Cucumber random failures in your Continuous Integration Service
Craftsmanship
De Código, Café y Cervezas 08 – Web Services
Community
De Código, Café y Cervezas 06 – ActiveModel::Serializer