DEV Community

Cover image for Pagination in Rails
rwparrish
rwparrish

Posted on

Pagination in Rails

In this blog, we will look at what pagination is and how to implement it into your Rails app.

Intro

Everybody has done some shopping on Amazon at some point. We live in the age of information and convenience. Before the school year started, I was shopping on Amazon for a new backpack with my daughter. Of course, there were more options than one could dream of and it would have taken us three lifetimes to look through them all.

This is where pagination comes in. With pagination, we can limit the number of items that are retrieved from the database and shown at a given point. It can be overwhelming to look at one page with hundreds or thousands of items on it. Why not show twenty or thirty items at a time instead? This is what pagination can do for us. Basically, it breaks up a large list into a sequence of smaller lists based on the specifications we give it.

Setting up

A quick internet search of "will_paginate" finds this. Before we continue, take a look at it. Setting up pagination is surprisingly simple. After you have read it, we walk through the setup step by step. We will reference

Step 1

First, we need to install the pagination gem:

// in the Gemfile

gem 'will_paginate', '~> 3.1.0'
Enter fullscreen mode Exit fullscreen mode

Then run bundle install from the terminal.

Step 2

In my app, I have a couple of places I want to be able to implement pagination. First, I will head to the controller(s) and make the necessary code changes there. We get this line of code from the documentation - Post.paginate(page: params[:page], per_page: 30). In the controller the code currently looks like this:

class ArticlesController < ApplicationController

def index
  @articles = Article.all
end
...
Enter fullscreen mode Exit fullscreen mode

The code in the index action gets changed:

def index
  @articles = Article.paginate(page: params[:page], per_page: 5)
end
Enter fullscreen mode Exit fullscreen mode

Now, the @articles instance variable will hold only a certain number of items from the database according to our specifications. In this case, I specify that each page should show five items.

Step 3

Again, referring to the documentation, we are given this line of code - <%= will_paginate @posts %>. So, in the appropriate view (articles/index.html.erb in this case):

<h1 class="text-center mt-4">This is the index page</h1>

<%= render 'article' %>
Enter fullscreen mode Exit fullscreen mode

The following code is added:

<h1 class="text-center mt-4">This is the index page</h1>

<div class="apple_pagination">
  <%= will_paginate @articles, :container => false %>
</div>

<%= render 'article' %>

<div class="apple_pagination">
  <%= will_paginate @articles, :container => false %>
</div>
Enter fullscreen mode Exit fullscreen mode

I'm sure you noticed a couple of things. I wanted to render the pagination at the top and the bottom of the page. Also, I added some styling. You can do the same by following the link - make those pagination links prettier - in the documentation to here.

Recap

In this short and sweet read, pagination was covered. We learned:

  1. Pagination breaks up a large list into a sequence of smaller lists based on the specifications we give it.
  2. It is pretty darn simple to implement!

I hope you learned something new. Happy coding!

Oldest comments (6)

Collapse
 
kinnalru profile image
Samoilenko Yuri

Total count which using to calculate page count will cause full database scan. So be careful and prepared when total items count start approaching a ~ 1M

Collapse
 
rwparrish profile image
rwparrish

Good point. Thanks for sharing!

Collapse
 
thorstenhirsch profile image
Thorsten Hirsch

This kind of pagination lead to a dead-end for my use case, because my users wanted sort and search the data. Sure there might be a hacky way to forward the search term and the sort key from client to server and let the server do the sorting & searching before the pagination, but with all the requests and replies it's not the best user experience. So my advise is: unless you have thousands of records you should send all data to the browser and do pagination there with a JS library.

Collapse
 
rwparrish profile image
rwparrish

I actually thought about sorting and searching while I was implementing this. That is something I would like to try implementing in a future project. Thanks for the input.

Collapse
 
swiknaba profile image
Lud

Nowadays I would use Pagy instead of will paginate. Back then already Kaminari was better IMHO.
github.com/ddnexus/pagy

Collapse
 
rwparrish profile image
rwparrish

I'll check em out. Thanks for sharing!