Home

Awesome

Pagy

<span>Gem Version</span> <span> Ruby</span> <span> Ruby Test</span> <span> E2E Test</span> <span> Coverage</span> <span> Rubocop Status</span> <span> MIT license</span> <span> Commits</span> <span> Downloads</span> <span> Stars</span>

🏆 The Best Pagination Ruby Gem 🥇


<!-- whats_new_start -->

✴ What's new in 9.0+ ✴

<!-- whats_new_end -->

🚀 🚀 🚀 🚀 🚀

<img src="docs/assets/images/ips-chart.png" title="~40x Faster!"> <img src="docs/assets/images/memory-chart.png" title="~36x Lighter!"> <img src="docs/assets/images/objects-chart.png" title="~35x Simpler!"> <img src="docs/assets/images/resource-consumption-chart.png" title="1,410x More Efficient!">

<details>

Each dot in the visualization above represents the resources that Pagy consumes for one full rendering. The other gems consume hundreds of times as much for the same rendering.

The IPS/Kb ratio is calculated out of speed (IPS) and Memory (Kb): it shows how well each gem uses each Kb of memory it allocates/consumes.

Notice: the above charts refers to the comparison of the basic pagy v3.0.0 helper with will_paginate v3.1.7 and kaminari v1.1.1.

While it's not up-to-date, you can expect roughly similar results with the latest versions, maybe a bit less dramatic in performance due to the multiple features added to pagy since v3 (e.g. customizable and translated aria-labels). However, consider that the difference become A LOT bigger in favor of pagy if you use *nav_js helpers, Pagy::Countless or JSON and client side pagination that are not part of the comparison because missing in the other gems.

See the Detailed Gems Comparison for full details.

</details> <br>

🤩 It does it all. Better.

😎 It's easy to use and customize

<details open> <summary>Code for basic pagination...</summary>
# Include it in the controllers (e.g. application_controller.rb)
include Pagy::Backend

# Include it in the helpers (e.g. application_helper.rb)
include Pagy::Frontend

# Wrap your collections with pagy in your actions
@pagy, @records = pagy(Product.all)

Optionally set your defaults in the pagy initializer:

# Optionally override some pagy default with your own in the pagy initializer
Pagy::DEFAULT[:limit] = 10 # items per page
Pagy::DEFAULT[:size]  = 9  # nav bar links
# Better user experience handled automatically
require 'pagy/extras/overflow'
Pagy::DEFAULT[:overflow] = :last_page
<%# Render a view helper in your views (skipping nav links for empty pages) %>
<%== pagy_nav(@pagy) if @pagy.pages > 1 %>

Or, choose from the following view helpers:

View Helper NamePreview (Bootstrap Style shown)
pagy_nav(@pagy)pagy_nav
pagy_nav_js(@pagy)pagy_nav_js
pagy_info(@pagy)pagy_info
pagy_combo_nav_js(@pagy)pagy_combo_nav_js
pagy_limit_selector_jspagy_limit_selector_js
pagy_nav(@calendar[:year])<br/>pagy_nav(@calendar[:month])<br/> (other units: :quarter, :week, :day and custom)calendar extra

(See the Quick Start)

</details> <details> <summary>Customization for CSS frameworks...</summary>
# Require a CSS framework extra in the pagy initializer (e.g. bootstrap)
require 'pagy/extras/bootstrap'
<%# Use it in your views %>
<%== pagy_bootstrap_nav(@pagy) %>

(See all the CSS Framework Extras)

</details> <details> <summary>Customization for special collections...</summary>
# Require some special backend extra in the pagy initializer (e.g. elasticsearch_rails)
require 'pagy/extras/elasticsearch_rails'

# Extend your models (e.g. application_record.rb)
extend Pagy::ElasticsearchRails

# Use it in your actions
response         = Article.pagy_search(params[:q])
@pagy, @response = pagy_elasticsearch_rails(response)

(See all the Search Extras)

</details> <details> <summary>Customization for client-side|JSON rendering...</summary>
# Require the metadata extra in the pagy initializer
require 'pagy/extras/metadata'

# Use it in your actions
pagy, records = pagy(Product.all)
render json: { data: records,
               pagy: pagy_metadata(pagy) }

(See all the Backend Tools)

</details> <details> <summary>Customization for headers pagination for APIs...</summary>
# Require the headers extra in the pagy initializer
require 'pagy/extras/headers'

# Use it in your actions
pagy, records = pagy(Product.all)
pagy_headers_merge(pagy)
render json: records

(See all the Backend Tools)

</details> <details> <summary>Customization for JSON:API pagination...</summary>
# Require the jsonapi extra in the pagy initializer
require 'pagy/extras/jsonapi'

# Use it in your actions
pagy, records = pagy(Product.all)
render json: { data:  records,
               links: pagy_jsonapi_links(pagy) }
# besides the query params will be nested. E.g.: ?page[number]=2&page[size]=100

(See all the Backend Tools)

</details> <br>

More customization with Extras that add special options and manage different components, behaviors, Frontend or Backend environments... usually by just requiring them (and optionally overriding some default).

See also the How To Page

🤓 It's well documented and supported

Documentation

Support

Posts and tutorials

Screencasts

<img src="https://img.youtube.com/vi/1tsWL4EjhMo/0.jpg" width="150" title="15 min - Beginner friendly - Shows installation and use of some pagy extras"> <img src="https://img.youtube.com/vi/ScxUqW29F7E/0.jpg" width="150" title="18 min - Intermediate Skill Level - 'Load More' pagination using Turbo Streams"> <img src="https://img.youtube.com/vi/A9q6YwhLCyI/0.jpg" title="17 min - Intermediate Skill Level - Pagination with Search (Ransack) and Hotwire + Infinite (Countless) Pagination" width="150"> <img src="https://img.youtube.com/vi/Qoq6HZ8gdDE/0.jpg" title="12:52 min - Intermediate Skill Level - API based pagination + using pagy_metadata" width="150"> <img src="https://img.youtube.com/vi/EDyZIB8FU-g/0.jpg" title="12:52 min - Intermediate Skill Level - Calendar sarch with Pagy" width="150"> <img src="https://img.youtube.com/vi/K4fob588tfM/0.jpg" width="150" title="11 min - Beginner - How to Install + 'Hello world' example"> <img src="https://img.youtube.com/vi/1sNpvTMrxl4/0.jpg" width="150" title="31 min - Beginner - Basic Pagy Use (Tailwind, Overflow, Common Use cases) + Deep dive into building a sample Blogging Application"> <img src="https://img.youtube.com/vi/0RtYhDIKmBY/0.jpg" width="150" title="5:44 min - Beginner - How to Install Pagy + Using Tailwind CSS to create a page of 'listing'"> <img src="https://img.youtube.com/vi/aILtxj_LVuA/0.jpg" width="150" title="7:23 min - Beginner - Installing Pagy + Working through errors (step-by-step)"> <img src="https://img.youtube.com/vi/bVvLNpJyZuw/0.jpg" width="150" title="9:29 min - Intermediate - Infinite Scrolling with Pagy Keyset, Turbo (Rails 8)"> <img src="https://img.youtube.com/vi/ArBUAxEA6vM/0.jpg" width="150" title="30:00 min - Advanced - Using Pagy In the Context of a Chat Room (Infinite Scroll, Hotwire, Stimulus JS + Using Pagy APIs)"> <img src="https://img.youtube.com/vi/4nrmf5KfD8Y/0.jpg" width="150" title="14:28 min - Intermediate - Infinite Scrolling with Turbo Streams (Rails 7)"> <img src="https://img.youtube.com/vi/HURqvNJF4T0/0.jpg" width="150" title="5:21 min - Intermediate - Using Pagy - with a strong focus on Hotwire and filtering search results"> <img src="https://img.youtube.com/vi/_j3gtKf5rRs/0.jpg" width="150" title="10:45 - Spanish Language"> <img src="https://img.youtube.com/vi/zni3nMA5_AY/0.jpg" width="150" title="10:53 - Urdu Language">

<br>

Top 💯 Contributors

<!-- top100_start -->

<img src="https://avatars.githubusercontent.com/u/100721?v=4" width="40" title="@ddnexus: 1692 contributions"><img src="https://avatars.githubusercontent.com/u/15097447?v=4" width="40" title="@benkoshy: 76 contributions"><img src="https://avatars.githubusercontent.com/u/11367?v=4" width="40" title="@grosser: 9 contributions"><img src="https://avatars.githubusercontent.com/u/14981592?v=4" width="40" title="@Earlopain: 4 contributions"><img src="https://avatars.githubusercontent.com/u/9843321?v=4" width="40" title="@workgena: 4 contributions"><img src="https://avatars.githubusercontent.com/u/32258?v=4" width="40" title="@espen: 3 contributions"><img src="https://avatars.githubusercontent.com/u/26239269?v=4" width="40" title="@enzinia: 3 contributions"><img src="https://avatars.githubusercontent.com/u/132?v=4" width="40" title="@sunny: 3 contributions"><img src="https://avatars.githubusercontent.com/u/235048?v=4" width="40" title="@molfar: 3 contributions"><img src="https://avatars.githubusercontent.com/u/22333?v=4" width="40" title="@bquorning: 3 contributions"><img src="https://avatars.githubusercontent.com/u/17091381?v=4" width="40" title="@djpremier: 3 contributions"><img src="https://avatars.githubusercontent.com/u/3427854?v=4" width="40" title="@747: 2 contributions"><img src="https://avatars.githubusercontent.com/u/195636?v=4" width="40" title="@tersor: 2 contributions"><img src="https://avatars.githubusercontent.com/u/1100176?v=4" width="40" title="@thomasklemm: 2 contributions"><img src="https://avatars.githubusercontent.com/u/37790?v=4" width="40" title="@gamafranco: 2 contributions"><img src="https://avatars.githubusercontent.com/u/500826?v=4" width="40" title="@tiagotex: 2 contributions"><img src="https://avatars.githubusercontent.com/u/112558900?v=4" width="40" title="@wimdavies: 2 contributions"><img src="https://avatars.githubusercontent.com/u/7076736?v=4" width="40" title="@renshuki: 2 contributions"><img src="https://avatars.githubusercontent.com/u/2749593?v=4" width="40" title="@berniechiu: 2 contributions"><img src="https://avatars.githubusercontent.com/u/12479464?v=4" width="40" title="@ashmaroli: 2 contributions"><img src="https://avatars.githubusercontent.com/u/3188392?v=4" width="40" title="@cseelus: 2 contributions"><img src="https://avatars.githubusercontent.com/u/50970645?v=4" width="40" title="@sabljak: 2 contributions"><img src="https://avatars.githubusercontent.com/u/421488?v=4" width="40" title="@petergoldstein: 2 contributions"><img src="https://avatars.githubusercontent.com/u/101501?v=4" width="40" title="@rainerborene: 2 contributions"><img src="https://avatars.githubusercontent.com/u/2051199?v=4" width="40" title="@rbngzlv: 2 contributions"><img src="https://avatars.githubusercontent.com/u/8125726?v=4" width="40" title="@simonneutert: 2 contributions"><img src="https://avatars.githubusercontent.com/u/9060346?v=4" width="40" title="@artplan1: 1 contribution"><img src="https://avatars.githubusercontent.com/u/310909?v=4" width="40" title="@serghost: 1 contribution"><img src="https://avatars.githubusercontent.com/u/1478773?v=4" width="40" title="@Tolchi: 1 contribution"><img src="https://avatars.githubusercontent.com/u/412056?v=4" width="40" title="@rogermarlow: 1 contribution"><img src="https://avatars.githubusercontent.com/u/4824537?v=4" width="40" title="@yenshirak: 1 contribution"><img src="https://avatars.githubusercontent.com/u/7660738?v=4" width="40" title="@rafaelmontas: 1 contribution"><img src="https://avatars.githubusercontent.com/u/32079912?v=4" width="40" title="@rafaeelaudibert: 1 contribution"><img src="https://avatars.githubusercontent.com/u/2815199?v=4" width="40" title="@pedrocarmona: 1 contribution"><img src="https://avatars.githubusercontent.com/u/211?v=4" width="40" title="@olleolleolle: 1 contribution"><img src="https://avatars.githubusercontent.com/u/12237543?v=4" width="40" title="@olieidel: 1 contribution"><img src="https://avatars.githubusercontent.com/u/1012014?v=4" width="40" title="@okuramasafumi: 1 contribution"><img src="https://avatars.githubusercontent.com/u/43544760?v=4" width="40" title="@WilliamHorel: 1 contribution"><img src="https://avatars.githubusercontent.com/u/23448075?v=4" width="40" title="@woller: 1 contribution"><img src="https://avatars.githubusercontent.com/u/30351533?v=4" width="40" title="@sk8higher: 1 contribution"><img src="https://avatars.githubusercontent.com/u/58137134?v=4" width="40" title="@muhammadnawzad: 1 contribution"><img src="https://avatars.githubusercontent.com/u/69295?v=4" width="40" title="@ronald: 1 contribution"><img src="https://avatars.githubusercontent.com/u/10906059?v=4" width="40" title="@achmiral: 1 contribution"><img src="https://avatars.githubusercontent.com/u/1393996?v=4" width="40" title="@mauro-ni: 1 contribution"><img src="https://avatars.githubusercontent.com/u/462701?v=4" width="40" title="@borama: 1 contribution"><img src="https://avatars.githubusercontent.com/u/24856?v=4" width="40" title="@creativetags: 1 contribution"><img src="https://avatars.githubusercontent.com/u/24826?v=4" width="40" title="@mcary: 1 contribution"><img src="https://avatars.githubusercontent.com/u/93276?v=4" width="40" title="@marckohlbrugge: 1 contribution"><img src="https://avatars.githubusercontent.com/u/1753398?v=4" width="40" title="@fluser: 1 contribution"><img src="https://avatars.githubusercontent.com/u/6563823?v=4" width="40" title="@maful: 1 contribution"><img src="https://avatars.githubusercontent.com/u/7241024?v=4" width="40" title="@AngelGuerra: 1 contribution"><img src="https://avatars.githubusercontent.com/u/18153165?v=4" width="40" title="@tr4b4nt: 1 contribution"><img src="https://avatars.githubusercontent.com/u/4953187?v=4" width="40" title="@tiejianluo: 1 contribution"><img src="https://avatars.githubusercontent.com/u/28652?v=4" width="40" title="@szTheory: 1 contribution"><img src="https://avatars.githubusercontent.com/u/22420?v=4" width="40" title="@smoothdvd: 1 contribution"><img src="https://avatars.githubusercontent.com/u/87665329?v=4" width="40" title="@rhodes-david: 1 contribution"><img src="https://avatars.githubusercontent.com/u/5484758?v=4" width="40" title="@radinreth: 1 contribution"><img src="https://avatars.githubusercontent.com/u/54139019?v=4" width="40" title="@pranavbabu: 1 contribution"><img src="https://avatars.githubusercontent.com/u/884634?v=4" width="40" title="@okliv: 1 contribution"><img src="https://avatars.githubusercontent.com/u/5013677?v=4" width="40" title="@nedimdz: 1 contribution"><img src="https://avatars.githubusercontent.com/u/468744?v=4" width="40" title="@msdundar: 1 contribution"><img src="https://avatars.githubusercontent.com/u/59817964?v=4" width="40" title="@m-abdurrehman: 1 contribution"><img src="https://avatars.githubusercontent.com/u/831536?v=4" width="40" title="@dwieringa: 1 contribution"><img src="https://avatars.githubusercontent.com/u/29891001?v=4" width="40" title="@jyuvaraj03: 1 contribution"><img src="https://avatars.githubusercontent.com/u/6220668?v=4" width="40" title="@YutoYasunaga: 1 contribution"><img src="https://avatars.githubusercontent.com/u/65494027?v=4" width="40" title="@iamyujinwon: 1 contribution"><img src="https://avatars.githubusercontent.com/u/13119624?v=4" width="40" title="@yhk1038: 1 contribution"><img src="https://avatars.githubusercontent.com/u/6612882?v=4" width="40" title="@ya-s-u: 1 contribution"><img src="https://avatars.githubusercontent.com/u/13472945?v=4" width="40" title="@yshmarov: 1 contribution"><img src="https://avatars.githubusercontent.com/u/190269?v=4" width="40" title="@thattimc: 1 contribution"><img src="https://avatars.githubusercontent.com/u/7021119?v=4" width="40" title="@thomaschauffour: 1 contribution"><img src="https://avatars.githubusercontent.com/u/361323?v=4" width="40" title="@snkashis: 1 contribution"><img src="https://avatars.githubusercontent.com/u/6059188?v=4" width="40" title="@sliminas: 1 contribution"><img src="https://avatars.githubusercontent.com/u/9826538?v=4" width="40" title="@LuukvH: 1 contribution"><img src="https://avatars.githubusercontent.com/u/6208777?v=4" width="40" title="@Federico-G: 1 contribution"><img src="https://avatars.githubusercontent.com/u/18742365?v=4" width="40" title="@egimenos: 1 contribution"><img src="https://avatars.githubusercontent.com/u/73437?v=4" width="40" title="@elliotlarson: 1 contribution"><img src="https://avatars.githubusercontent.com/u/17459154?v=4" width="40" title="@hungdiep97: 1 contribution"><img src="https://avatars.githubusercontent.com/u/6763624?v=4" width="40" title="@davidwessman: 1 contribution"><img src="https://avatars.githubusercontent.com/u/813150?v=4" width="40" title="@david-a-wheeler: 1 contribution"><img src="https://avatars.githubusercontent.com/u/1169363?v=4" width="40" title="@daniel-rikowski: 1 contribution"><img src="https://avatars.githubusercontent.com/u/8194848?v=4" width="40" title="@connie-feng: 1 contribution"><img src="https://avatars.githubusercontent.com/u/83706?v=4" width="40" title="@MrMoins: 1 contribution"><img src="https://avatars.githubusercontent.com/u/67093?v=4" width="40" title="@excid3: 1 contribution"><img src="https://avatars.githubusercontent.com/u/5347394?v=4" width="40" title="@cellvinchung: 1 contribution"><img src="https://avatars.githubusercontent.com/u/4116980?v=4" width="40" title="@brunoocasali: 1 contribution"><img src="https://avatars.githubusercontent.com/u/42350151?v=4" width="40" title="@branson-simplethread: 1 contribution"><img src="https://avatars.githubusercontent.com/u/19940878?v=4" width="40" title="@BrandonKlotz: 1 contribution"><img src="https://avatars.githubusercontent.com/u/12526288?v=4" width="40" title="@benjaminwols: 1 contribution"><img src="https://avatars.githubusercontent.com/u/3390330?v=4" width="40" title="@Atul9: 1 contribution"><img src="https://avatars.githubusercontent.com/u/1328587?v=4" width="40" title="@amenon: 1 contribution"><img src="https://avatars.githubusercontent.com/u/482867?v=4" width="40" title="@artinboghosian: 1 contribution"><img src="https://avatars.githubusercontent.com/u/58791514?v=4" width="40" title="@antonzaharia: 1 contribution"><img src="https://avatars.githubusercontent.com/u/43855653?v=4" width="40" title="@PyrinAndrii: 1 contribution"><img src="https://avatars.githubusercontent.com/u/1060?v=4" width="40" title="@andrew: 1 contribution"><img src="https://avatars.githubusercontent.com/u/7662492?v=4" width="40" title="@AliOsm: 1 contribution"><img src="https://avatars.githubusercontent.com/u/147130?v=4" width="40" title="@AbelToy: 1 contribution"><img src="https://avatars.githubusercontent.com/u/1453563?v=4" width="40" title="@loed-idzinga: 1 contribution"><img src="https://avatars.githubusercontent.com/u/283251?v=4" width="40" title="@epeirce: 1 contribution"><img src="https://avatars.githubusercontent.com/u/3071529?v=4" width="40" title="@kobusjoubert: 1 contribution">

<!-- top100_end --> <br/>

👏 Credits

Many thanks to:

📦 Repository Info

<details> <summary>How to contribute</summary>

See Contributing

</details> <details> <summary>Versioning</summary> </details> <details> <summary>Branches</summary> </details> <br>

💞 Related Projects

Search rubygems.org

📃 License

MIT