Intro

In this post I will outline a method the paginate database records in a Rails 6 app using the Pagy. gem. I will also cover the process of styling the paging navbar with bootstrap and font awesome icons.

Software

The following software was used in this post.

  • Rails - 6.0.3.4
  • Pagy - 3.5
  • Bootstrap - 5.0.0-beta1
  • Font Awesome (Free) - 5.15.1
Note
Pagy works with any rack app, therefore it is not tightly integrated into rails and is a bit more involved to setup than other paging gems.

Installation

Add the Pagy gem to your Gemfile

file
# Gemfile

gem 'pagy', '~> 3.5'

Then use bundle to install the gem.

cmd
bundle install

Configuration

Include the Pagy backend into the app/controllers/application_controller.rb file.

file
# app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  include Pagy::Backend
end

Include the Pagy frontend into the app/helpers/application_helper.rb file.

file
# app/helpers/application_helper.rb

module ApplicationHelper
  include Pagy::Frontend
end

Copy the pagy.rb configuration file from here to your config/initializers/ directory.

This file is where you apply some of the customization for Pagy and also enable any extras.

file
# config/initializers/pagy.rb

# Uncomment this line to enable bootstrap.
require 'pagy/extras/bootstrap'

# Return 25 records per page.
Pagy::VARS[:items] = 25

# Change to layout of the paginator nav bar.
Pagy::VARS[:size] = [1,2,2,1]

To use font awesome icons create a partial paginator.html.erb template file in the app/views/shared/ directory.

I used the template from here. Replacing the pagy_t calls with the Font Awesome icon HTML as strings I want to use.

Here is a quote from the docs:

This template is i18n-ready: if you dont use i18n, then you can replace the pagy_t calls with the actual strings ("‹ Prev", "Next ›", "…").

- https://github.com/ddnexus/pagy/blob/master/lib/templates/bootstrap_nav.html.erb

For Example:
    From: pagy_t('pagy.nav.prev') To: '<i class="fas fa-angle-left"></i>'

The complete template is below.

file
# app/views/shared/paginator.html.erb

<% link = pagy_link_proc(pagy, 'class="page-link"') %>
<nav aria-label="pager"  class="pagy-bootstrap-nav" role="navigation">
  <ul class="pagination">
  <% if pagy.prev %>    
    <li class="page-item prev"><%== link.call(pagy.prev, '<i class="fas fa-angle-left"></i>', 'aria-label="previous"') %></li>
  <% else %>    
    <li class="page-item prev disabled"><a href="#" class="page-link"><%== '<i class="fas fa-angle-left"></i>' %></a></li>
  <% end -%>
  <% pagy.series.each do |item| %>
    <%# series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36] %>
    <% if item.is_a?(Integer) %>    
      <li class="page-item"><%== link.call(item) %></li>
    <% elsif item.is_a?(String) %>    
      <li class="page-item active"><%== link.call(item) %></li>
    <% elsif item == :gap %>    
      <li class="page-item disabled gap"><a href="#" class="page-link"><%== '<i class="fas fa-ellipsis-h"></i>' %></a></li>
    <% end %>
  <% end %>
  <% if pagy.next %>    
      <li class="page-item next"><%== link.call(pagy.next, '<i class="fas fa-angle-right"></i>', 'aria-label="next"') %></li>
    <% else %>    
      <li class="page-item next disabled"><a href="#" class="page-link"><%== '<i class="fas fa-angle-right"></i>' %></a></li>
  <% end %>
  </ul>
</nav>

Now, Because we altered an initializer, restart your rails server to apply the changes.

Usage

In the controller actions that require paging. Wrap you queries in pagy calls.

file
# app/controllers/devices_controller.rb

class DevicesController < ApplicationController
  def index
    @pagy, @devices = pagy(Devices.all)
  end
end

In the associated views render the paginator partial template created in a previous step.

file
# app/views/devices/index.html.erb

<%= render partial: "shared/paginator", locals: { pagy: @pagy }%>

And that's it. Behold the blazing fast beauty of Pagy.

Outro

In this post we added pagination to a Rails 6 app using the Pagy gem. We also used Bootstrap to style the paginator and used Font Awesome icons for the navigators and seperator.