Ruby on Rails

How to install pagy gem with a custom pagination template on a Ruby on Rails application

This minipost will guide you through all the required steps in order to successfully install pagy gem for pagination on a Ruby on Rails application using a custom HTML template.

Pagy gem installation steps

Start by adding the pagy gem to your application Gemfile [appname/Gemfile] by:

gem 'pagy', '~> 3.0.0'

Go to the application directory [appname]:

cd appname

and perform bundle install inside directory to install the pagy gem:

bundle install

Before you start developing the pagination view, you need to include two separate pagy modules, they are called: Pagy::Backend and Pagy::Frontend in different parts of your application.

Include Pagy::Backend module to your application_controller.rb or only in a specific controller depending on where you will use pagination. If you have multiple controllers offering pagination, a good place to include this is the controller that all the other controllers inherit from(i.e. ApplicationController [appname/app/controllers/application_controller.rb])

We are going to include the module in ApplicationController[appname/app/controllers/application_controller.rb]:

# Application controller
class ApplicationController < ActionController::Base
  # Pagy
  include Pagy::Backend
end

Now, it's time to include the Pagy::Frontend module. We will include it in ApplicationHelper [app/helpers/application_helper.rb]:

module ApplicationHelper
  # Pagy
  include Pagy::Frontend
end

Having both the include-s in place, we need to add the relevant Rails partial with the pagination HTML code.

Important here to notice is that by using the default pagination integrations of pagy with bootstrap or other frameworks, you achieve even faster results in speed. However, when the project you are working on has custom HTML pagination, the easiest way is to use a rails partial to customize the pagination implementation.

Pagy offers HTML templates to start customization. Navigate to pagy haml pagination template and copy the template content, create a partial _pagination.html.haml [app/views/shared/_pagination.html.haml] and paste the following template:

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

-# The link variable is set to a proc that returns the link tag.
-# Usage: link.call( page_number [, text [, extra_attributes_string ]])

- link = pagy_link_proc(pagy)

%nav.pagy_nav.pagination{"aria-label" => "pager", :role => "navigation"}

  - if pagy.prev
    %span.page.prev!= link.call(pagy.prev, pagy_t('pagy.nav.prev'), 'aria-label="previous"')
  - else
    %span.page.prev.disabled!= pagy_t('pagy.nav.prev')

  - pagy.series.each do |item|       # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
    - if item.is_a?(Integer)         # page link
      %span.page
        != link.call(item)

    - elsif item.is_a?(String)       # current page
      %span.page.current= item

    - elsif item == :gap             # page gap
      %span.page.gap!= pagy_t('pagy.nav.gap')

  - if pagy.next
    %span.page.next!= link.call(pagy.next, pagy_t('pagy.nav.next'), 'aria-label="next"')
  - else
    %span.page.next.disabled!= pagy_t('pagy.nav.next')

You can now start editing the template and alter the HTML provided with your own custom HTML markup. If you are not using HAML, there is the pagy html erb pagination template and there is also the pagy slim pagination template to start the implementation.

Choose the preferred one and edit the HTML code with your own custom markup.

Let's assume that you are willing to paginate a posts controller index action where all the posts are being displayed. Jump to the controller you are willing to implement pagination and add the following pagy line:

class PostsController < ApplicationController
  def index
    @pagy, @posts = pagy(Post.all.order(created_at: :desc))
  end
end

You are free to choose any selection and ordering, for simplicity, I have used Post.all.order(created_at: :desc). Alter the collection inside the brackets with your preferred collection for pagination.

Having the @pagy variable on your controller action, you are now ready to add the pagination layout to the relevant view.

Navigate to [app/views/posts/index.html.haml] or in your relevant view for the above controller setup and add the following render partial in the place you want to yield the pagination template:

= render partial: 'shared/pagination', locals: { pagy: @pagy }

Refresh your application, and there you go, you now have your pagination component rendered.

Two more, things before you go.

The pagy.rb initializer

You can use the pagy.rb initializer that comes with many options to customize the implementation. For this minipost, I will use only the default pagination items per page. All other options have been omitted for brevity(more options at pagy.rb initializer). Copy the following content to your pagy.rb [appname/app/config/initializers/pagy.rb] initializer

[..]
# Instance variables
# See https://ddnexus.github.io/pagy/api/pagy#instance-variables
Pagy::VARS[:items] = 10
[..]

In the above initializer, we have set the default pagination items per page to 10 items across all pagy implementations inside the application.

Alternatively, you can set directly in the pagy controller call the items per page that you want to get paginated in your view, overriding the general setting of the pagy.rb initializer, by:

@pagy, @posts = pagy(Post.all.order(created_at: :desc), items: 20)

The above will paginate 20 items per page.

Pagy i18n localization

Pagy also offers i18n localization and by default supports the following locales: en, es, fr and a couple more.

If your locale is not on the list, you can copy the en localization file from pagy en locale file and add your custom locales. For the above _pagination.html.haml I have used only the following 3 locale variables for the el locale [config/locales/pagy.el.yml].

el:
  pagy:
    nav:
      prev: "‹ Προηγούμενη"
      next: "Επόμενη ›"
      gap: "…"

Additional information:

Buy Me A Coffee

Read also the following