Agnostic pagination in plain Ruby
Tip
โญ If you like Pagy, please support it with a Star! โญ
- Compatible with all environments and collection types
- It can use OFFSET, COUNTISH, COUNTLESS, KEYSET, KEYNAV, SEARCH, and CALENDAR pagination techniques
- It supports server-side rendering or faster client-side rendering for popular CSS frameworks and APIs
- It autoloads ONLY the methods that you actually use, with almost zero configuration
- It boasts 100% test coverage for Ruby, HTML, and JavaScript end-to-end (E2E)
# Include pagy in your code (usually application_controller.rb)
include Pagy::Method
# Offset-based pagination
@pagy, @records = pagy(:offset, Product.all)
# Keyset-based pagination (fastest technique)
@pagy, @records = pagy(:keyset, Product.order(my_order).all)
# Paginate your collection with one of several paginators
@pagy, @records = pagy(...)See all the available paginators
# JSON:API nested query string. E.g.: ?page[number]=2&page[size]=100
@pagy, @records = pagy(:offset, Product.all, jsonapi: true)
@pagy, @records = pagy(:keyset, Product.order(my_order).all, jsonapi: true)
render json: { links: @pagy.urls_hash, data: @records }render json: { pagy: @pagy.data_hash, data: @records }Available paginators: :elasticsearch_rails, :meilisearch, :rails_active_search, :searchkick, :typesense_rails
# Extend your models (e.g. application_record.rb)
extend Pagy::Search
# Paginate with pagy:
search = Product.pagy_search(params[:q])
@pagy, @response = pagy(:a_search_paginator, search)
# Or get pagy from paginated results:
@results = Product.search(params[:q])
@pagy = pagy(:a_search_paginator, @results)Combine time-range and offset pagination.
(Available time units: year, quarter, month, week, and day)
@calendar, @pagy, @records = pagy(:calendar, collection, year: {}, month: {}, offset: {})<%== @calendar[:year].series_nav(:bootstrap) %>
<%== @calendar[:month].series_nav(:bootstrap) %>
<%== @pagy.info_tag %>
...
<%== @pagy.series_nav(:bootstrap) %>Default :pagy, :bootstrap and :bulma styles shown.
<!-- Render server side nav bar helpers with different html and styles -->
<%== @pagy.series_nav %> <!-- pagy style -->
<%== @pagy.series_nav(:bootstrap) %>
<%== @pagy.series_nav(:bulma) %># pagy.rb initializer
javascript_dir = Rails.root.join('app/javascript')
Pagy.sync_javascript(javascript_dir, 'pagy.mjs') if Rails.env.development?Faster and responsive
Dynamically fills the container width.
<!-- Render client side nav bar helpers with different html and styles -->
<%== @pagy.series_nav_js %> <!-- pagy style -->
<%== @pagy.series_nav_js(:bootstrap) %>
<%== @pagy.series_nav_js(:bulma) %>Fastest! Combines navigation and info in minimum space.
<!-- Render client side nav input helpers with different html and styles -->
<%== @pagy.input_nav_js %> <!-- pagy style -->
<%== @pagy.input_nav_js(:bootstrap) %>
<%== @pagy.input_nav_js(:bulma) %>Integrate pagy with your app's themes interactively (watch demo), and ask specific questions to the Pagy AI right in your app! You need only a single line in your page/layout head to get the Pagy Wand and the Pagy AI:
<%== Pagy.dev_tools %>See Dev Tools
- Quick Start
- How To (quick recipes)
- Upgrade to 43 (from version 9 or earlier)
- Migrate from WillPaginate and Kaminari (practical guide)
- Discussions
- Issues
- Changelog
Tip
โญ If you like Pagy, please support it with a Star! โญ
โฆand 13,500+ more public repos on GitHub.
Special thanks to:
- JetBrains for their free open source license.
- Ben Koshy for his contributions to the documentation, user support and interaction with external frameworks.
- The Stargazers for their support.
How to contribute
See Contributing
Versioning
- Pagy follows the Semantic Versioning 2.0.0. Please check the Changelog for breaking changes introduced by major versions. Using pessimistic version constraint in your Gemfile will ensure smooth upgrades.
Branches
- The
masterbranch is the latest rubygem-published release. It also contains docs and comment changes that don't affect the published code. It is never force-pushed. - The
devbranch is the development branch with the new code that will be merged in the next release. It could be force-pushed. - Expect any other branch to be internal, experimental, force-pushed, rebased and/or deleted even without merging.












