ruby

Is Pagy the Secret Weapon for Blazing Fast Pagination in Rails?

Pagy: The Lightning-Quick Pagination Tool Your Rails App Needs

Is Pagy the Secret Weapon for Blazing Fast Pagination in Rails?

When you’re diving into the world of handling large datasets in Ruby on Rails, you’ll quickly realize that pagination is your best friend. It not only makes the user experience smoother but also boosts the overall performance of your application. With a bunch of pagination gems out there, Pagy often snags the spotlight. Why? Well, because it’s blazing fast, super lightweight, and extremely flexible. If you’re ready to up your Rails game and paginate like a pro, this guide will walk you through making the most out of Pagy.

What’s So Special About Pagy?

Pagy is all about speed and efficiency. When dealing with big data, you need something that doesn’t hog resources. It outdoes other popular pagination gems like Kaminari and will_paginate in terms of both speed and memory efficiency. For instance, the nav_js helpers provided by Pagy are about 40 times faster and 36 times lighter than what Kaminari offers. If you’re running a high-traffic website, Pagy is a very compelling choice.

Getting Pagy Up and Running

To kick things off, you need to install Pagy in your Rails application. It’s pretty straightforward. Here’s how you go about it:

First, add the Pagy gem to your Gemfile:

gem 'pagy', '~> 3.0.0'

Then, run the following command in your terminal:

bundle install

Next, you need to include Pagy’s modules in your application. A good place to do this is in your ApplicationController:

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

This ensures that pagination is available across all controllers inheriting from ApplicationController.

Tweaking Pagy to Fit Your Needs

Pagy is flexible and allows you to tweak various aspects of pagination via an initializer file. To get going, create an initializer:

# config/initializers/pagy.rb
Pagy::VARS[:items] = 10

This snippet sets the default number of items per page to 10. If you want to paginate a different number of items on a particular page, you can override this setting directly in your controller:

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

In this example, the @posts collection is paginated to display 20 items per page.

How to Implement Pagination

To implement pagination in your controller actions, you’ll use the pagy method. Here’s a quick example:

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

Now, in your view, add the following to render the pagination links:

<%= pagy_nav(@pagy) %>

This snippet will generate all the necessary pagination links directly in your view.

Making Pagination Look Good

Pagy lets you customize the pagination templates to match your application’s design. This means you can create custom HTML for your pagination links. Here’s how:

First, create a custom template:

<nav class="pagination">
  <%= link_to "Previous", url_for(page: @pagy.prev), class: "prev" if @pagy.prev %>
  <% @pagy.pages.each do |item| %>
    <% if item == :gap %>
      <span class="gap">&hellip;</span>
    <% else %>
      <%= link_to item, url_for(page: item), class: ("active" if item == @pagy.page) %>
    <% end %>
  <% end %>
  <%= link_to "Next", url_for(page: @pagy.next), class: "next" if @pagy.next %>
</nav>

Save this file as _pagination.html.erb in the app/views/pagy directory. To use this custom template in your views:

<%= render 'pagy/pagination', pagy: @pagy %>

And just like that, you’ve got fully customized pagination links!

Handling Slow Count Queries

A big choke point in pagination is the count query, especially when you’re dealing with massive datasets. Pagy has some neat tricks to help you dodge this issue.

Caching the Count

You can cache the count of the collection to avoid hitting the database with a count query on every page load. Here’s a simple way to do this:

def pagy_get_count(collection, _vars)
  cache_key = "pagy-#{collection.model.name}:#{collection.to_sql}"
  Rails.cache.fetch(cache_key, expires_in: 20 * 60) do
    collection.count(:all)
  end
end

This will cache the result of the count query, which can be significantly faster.

Going Countless

Pagy’s countless feature eliminates the need for a count query by just adding 1 to the limit condition, which is particularly helpful for UIs where minimalism or automatism is key:

@pagy, @posts = pagy(Post.all.order(created_at: :desc), count: false)

This method completely skips the count query, giving a substantial performance boost for large datasets.

Language Support

Got an international audience? Pagy has your back with built-in internationalization (i18n). You can localize your pagination links effortlessly.

Adding a Custom Locale

Say you need to add Greek localization. It starts with creating a locale file named pagy.el.yml in your config/locales directory:

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

After setting your application to use the correct locale, Pagy fetches and uses these localized strings automatically for your pagination links.

Boosting Performance

Pagy isn’t just about good looks; it’s also about blazing fast performance.

Leveraging nav_js Helpers

The nav_js helpers use client-side rendering, making it incredibly faster and lighter than server-side rendering:

<%= pagy_nav_js(@pagy) %>

This approach renders the pagination links using JavaScript, giving you a smoother experience.

Combining nav_js and Combo_nav_js

For apps that need both navigation links and total feedback:

<%= pagy_combo_nav_js(@pagy) %>

This method pairs well with the oj gem for super-efficient front-end and back-end interactions.

Keyset Pagination

For humongous data, keyset pagination is your friend. Pagy supports this, and it’s generally more efficient than traditional offset-based pagination, especially when working with ActiveRecord::Relation or Sequel::Dataset.

Wrapping It Up

Pagy isn’t just another pagination gem; it’s a powerhouse designed for performance, efficiency, and flexibility. Whether you’re handling heaps of data or simply want a faster, lighter solution, Pagy fits right in. By following these steps, Pagy can be seamlessly integrated into your Rails application, making pagination smoother and more efficient, enhancing not just your app’s performance but also the overall user experience.

Keywords: Ruby on Rails, pagination, Pagy gem, Rails performance, large datasets, Pagy setup, Pagy customization, pagination efficiency, caching count queries, internationalization



Similar Posts
Blog Image
11 Powerful Ruby on Rails Error Handling and Logging Techniques for Robust Applications

Discover 11 powerful Ruby on Rails techniques for better error handling and logging. Improve reliability, debug efficiently, and optimize performance. Learn from an experienced developer.

Blog Image
Building Bulletproof Observability Pipelines in Ruby on Rails Applications

Master Rails observability with middleware, structured logging, and distributed tracing. Learn custom metrics, error tracking, and sampling strategies to build production-ready monitoring pipelines. Boost performance today.

Blog Image
Is Aspect-Oriented Programming the Missing Key to Cleaner Ruby Code?

Tame the Tangles: Dive into Aspect-Oriented Programming for Cleaner Ruby Code

Blog Image
**Advanced Rails Caching Strategies: From Russian Doll to Distributed Locks for High-Traffic Applications**

Learn advanced Rails caching strategies including Russian Doll patterns, low-level caching, HTTP headers, and distributed locks to optimize high-traffic applications. Boost performance and scale efficiently.

Blog Image
7 Essential Gems for Building Powerful GraphQL APIs in Rails

Discover 7 essential Ruby gems for building efficient GraphQL APIs in Rails. Learn how to optimize performance, implement authorization, and prevent N+1 queries for more powerful APIs. Start building better today.

Blog Image
Can Custom Error Classes Make Your Ruby App Bulletproof?

Crafting Tailored Safety Nets: The Art of Error Management in Ruby Applications