Better Views
Pagination
As our application data grows we frequently need pagination. In Rails 2 everyone used a gem named will_paginate
also referred to as mislav-will_paginate
.
Rails 3 brought a totally new model architecture under the hood of ActiveRecord, and the way will_paginate
hacked itself into the system doesn’t fit anymore. Thankfully there’s a new pagination library named Kaminari (https://github.com/amatsuda/kaminari) built from scratch for Rails 3 that fits in with the new ARel syntax.
Basics
There are three components to implementing pagination:
- Processing parameters to specify page and quantity-per-page
- Scoping the data queries based on those parameters
- Displaying page links
Processing Parameters
Typically applications will use a parameter named "page" in the request URL like this:
1
|
|
The Rails router will parse that URL parameter and make it available in params[:page]
.
Scoping Queries
Normally we would query our articles like this:
1
|
|
But when we call .all
, we get back an Array
. The query has already happened.
Using ActiveRelation
Delayed Queries
To use Kaminari’s pagination, we need to create an ActiveRelation object with:
1
|
|
This scope would find the same articles as Article.all
, but it delays running the query until we actually need the data. Since the query has not been run, Kaminari can still change it.
Kaminari’s page
Method
Kaminari adds two important methods that we can mix into ActiveRelation queries. The first is a page
method to specify which page we want:
1
|
|
By default it will limit each page to 25 elements.
Kaminari’s per
Method
To customize the number of items per page, we can add per
:
1
|
|
Or, more commonly, feed that page in from params
:
1
|
|
If page
is given nil
as a parameter, which will happen when the parameter is not present in the URL, Kaminari will return the first page.
Dealing with Links
Assuming that we have a collection @articles
that has been treated with per
and page
, in the view template we can write:
1
|
|
Exercises
Get the Blogger project from GitHub and run setup procedures:
1 2 3 4 5 |
|
All existing tests should pass. Optionally, run the tests continuously while developing by running guard
Getting Started with Kaminari
Open the Gemfile
and express the new dependency:
1
|
|
Save it and run bundle
from the project directory.
Generating More Sample Data
To flex the pagination, you might need to generate more sample data. Open up rails console
and run this code:
1
|
|
Now you should have at least 80 sample articles in the database.
Experimenting with Kaminari
Open app/controllers/articles_controller.rb
. We only need to paginate the index
. Currently it reads:
1 2 3 |
|
If you dig into the .search
class method in Article
, you’d find this:
1 2 3 4 5 6 7 8 |
|
The .search_by_tag_name
method is going to return a set of articles. We should be able to paginate them from the controller.
Paginating in the Controller
Let’s rewrite our index
method like this:
1 2 3 4 |
|
Refresh your browser and you should see just one page of articles.
Pagination in the View
When you look at the browser it is cut down to 10 articles, but there are no pagination links. Let’s add those now.
Open the app/views/articles/index.html.erb
template and add this at the bottom:
1
|
|
Refresh the view and you should see the page links show up.
Tweaking the Links
There are additional options available to control how many page links are rendered. If you are interested in customization, check out the Kaminari Recipes at https://github.com/amatsuda/kaminari/wiki/Kaminari-recipes
Respecting page
Click those links, though, and you’ll see our controller is not respecting the page
parameter. No matter which link we click we will see the same articles. Go back to the index
action in ArticlesController
and add the page
parameter like this:
1 2 3 4 |
|
Kaminari Wrap-Up
With a little more work you can implement AJAX pagination or even add I18n keys to control the display of your links. The documentation is available at https://github.com/amatsuda/kaminari