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'
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
...
The code in the index action gets changed:
def index
@articles = Article.paginate(page: params[:page], per_page: 5)
end
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' %>
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>
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:
- Pagination breaks up a large list into a sequence of smaller lists based on the specifications we give it.
- It is pretty darn simple to implement!
I hope you learned something new. Happy coding!
Top comments (6)
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.
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.
Nowadays I would use Pagy instead of will paginate. Back then already Kaminari was better IMHO.
github.com/ddnexus/pagy
I'll check em out. Thanks for sharing!
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
Good point. Thanks for sharing!