Pagination is an important aspect of most web applications. Luckily, in Ruby on Rails we have the ability to easily paginate our data using a gem called 'will_paginate'.

To get started, add the will_paginate gem to your gemfile.

Gemfile:

gem 'will_paginate', '~> 3.0'

Next, lets create a new model. In a new or existing project run the following command to create a model called 'Product'.

Terminal Commands:

rails g model Product name price:decimal{8,2} quantity:integer

To save time, I've created a list of products that you can import into your application. Download the seeds.rb file that I have created here and replace your existing db/seeds.rb file with it. If you already have some database seeds in place, just open this file and copy/paste them into the existing file. You may also simply use the example project provided at the top of this article.

Next, we need to run a few more terminal commands. Run the following commands below to migrate the database and add the seed data to your database.

Terminal Commands:

rake db:migrate
rake db:seed

Next, lets create a controller for our products. Run the following terminal command to create a new products controller.

Terminal Commands:

rails g controller Products index

Now open the products controller and modify it so that it looks like the code below.

app/controllers/products_controller.rb:

class ProductsController < ApplicationController
  def index
    @products = Product.all
  end
end

Now lets add code to the index view to show the list of products. Open the index view for our products controller and modify it so that it looks like the following code.

app/views/products/index.html.erb:

<table style="width:500px">
  <thead>
      <tr>
          <th>Name</th>
          <th style="text-align:right;">Price</th>
          <th style="text-align:right;">Quantity</th>
      </tr>
  </thead>
  <tbody>
      <% @products.each do |product| %>
          <tr>
            <td><%= product.name %></td>
            <td style="text-align:right;"><%= number_to_currency product.price %></td>
            <td style="text-align:right;"><%= product.quantity %></td>
          </tr>
      <% end %>
  </tbody>
</table>

Before we start our rails server to take a peak, modify the routes.rb file to look like the code listed below (making sure to replace 'WillPaginateExample' with your application name.)

config/routes.rb:

WillPaginateExample::Application.routes.draw do
  resources :products, only: [:index]
  root to: "products#index"
end

Now, if we start a rails server and visit http://localhost:3000 we will end up with the list shown below.

Will Paginate Screenshot 1

Now, lets add pagination to our application. Open your products controller again and modify it so that it looks like the following code.

app/controllers/products_controller.rb:

class ProductsController < ApplicationController
  def index
    @products = Product.all.paginate(page: params[:page], per_page: 5)
  end
end

Now lets modify our view and add the necessary code to render the pagination controls. Open your products index view and modify it so that it looks like the code below.

app/views/products/index.html.erb:

<%= will_paginate @products %>
<table style="width:500px">
  <thead>
  <tr>
    <th>Name</th>
    <th style="text-align:right;">Price</th>
    <th style="text-align:right;">Quantity</th>
  </tr>
  </thead>
  <tbody>
  <% @products.each do |product| %>
      <tr>
        <td><%= product.name %></td>
        <td style="text-align:right;"><%= number_to_currency product.price %></td>
        <td style="text-align:right;"><%= product.quantity %></td>
      </tr>
  <% end %>
  </tbody>
</table>
<%= will_paginate @products %>

Now if we visit http://localhost:3000 again we will see that pagination controls have been added and we can now page through our data!

Will Paginate Screenshot 1

Displaying only 5 items per page is a really low number however, we should increase the number of items displayed per page to make it easier to navigate. Open the products controller again and modify the per_page parameter of the paginate method so that it looks like the code listed below.

app/controllers/products_controller.rb:

class ProductsController < ApplicationController
  def index
    @products = Product.all.paginate(page: params[:page], per_page: 10)
  end
end

Visiting http://localhost:3000 again now shows us a much larger list with fewer pages.

Excellent! However, what if we want to style the pagination controls? It's actually pretty easy. Below is the code generated by the call to will_paginate:


<div class="pagination">
  <span class="previous_page disabled">&#8592; Previous</span> 
  <em class="current">1</em> 
  <a rel="next" href="/products?page=2">2</a> 
  <a href="/products?page=3">3</a> 
  <a href="/products?page=4">4</a> 
  <a class="next_page" rel="next" href="/products?page=2">Next &#8594;</a>
</div>

As you can see, there are actually a few different CSS classes being used. Modifying the styles for any one of these will result in a style change to will_paginate. Open up the products.css.scss file and modify it so that it looks like the code listed below.

app/assets/stylesheets/products.css.scss:

.pagination {
  .previous_page { background:#7777ff; color:white }
  .previous_page.disabled { background: white; color: #777 }
  .current { background: yellow }
  .next_page { background: #7777ff; color: white }
  .next_page.disabled { background: white; color: #777 }
}

Now if you visit http://localhost:3000 once again you'll see that the styles have changed. You can tweak these styles however you want to suit your needs.

That's it! If you have any comments or concerns, please feel free to leave them in the comments section listed below.