Receber por email
← Voltar para o catálogo

rails-pagination-kaminari

Pagination for Ruby on Rails applications using Kaminari. Use when: (1) Implementing pagination for database records, (2) Building paginated API endpoints, (3) Customizing pagination UI with themes, (4) Handling large datasets efficiently, (5) Creating infinite scroll, (6) Paginating arrays or custom collections, (7) Adding SEO-friendly pagination URLs, (8) Internationalizing pagination labels

13estrelas
Atualizado há 6 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add Shoebtamboli/rails_claude_skills

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/rails-pagination-kaminari/svg)](https://www.skillteca.com.br/skills/rails-pagination-kaminari)

Skills relacionadas

Ver todas de Dados e Análise →

Alerta por categoria

Receba novas skills de Dados e Análise toda segunda

1 email curto, só com as skills novas de Dados e Análise. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Rails Pagination with Kaminari

Kaminari is a scope and engine-based pagination library that provides a clean, powerful, customizable paginator for Rails applications. It's non-intrusive, chainable with ActiveRecord, and highly customizable.

Quick Setup

# Add to Gemfile
bundle add kaminari

# Generate configuration file (optional)
rails g kaminari:config

# Generate view templates for customization (optional)
rails g kaminari:views default

Basic Usage

Controller Pagination

# app/controllers/posts_controller.rb
class PostsController < ApplicationController
  def index
    @posts = Post.order(:created_at).page(params[:page])
    # Returns 25 items per page by default
  end
end

View Helper

<!-- app/views/posts/index.html.erb -->
<%= paginate @posts %>

That's it! Kaminari automatically adds pagination links.

Core Methods

Page Scope

# Basic pagination
User.page(1)                    # First page, 25 items
User.page(params[:page])        # Dynamic page from params

# Custom per-page
User.page(1).per(50)            # 50 items per page

# Chaining with scopes
User.active.order(:name).page(params[:page]).per(20)

# With associations
User.includes(:posts).page(params[:page])

Pagination Metadata

users = User.page(2).per(20)

users.current_page      #=> 2
users.total_pages       #=> 10
users.total_count       #=> 200
users.limit_value       #=> 20
users.first_page?       #=> false
users.last_page?        #=> false
users.next_page         #=> 3
users.prev_page         #=> 1
users.out_of_range?     #=> false

Configuration

Global Configuration

# config/initializers/kaminari_config.rb
Kaminari.configure do |config|
  config.default_per_page = 25        # Default items per page
  config.max_per_page = 100           # Maximum allowed per page
  config.max_pages = nil              # Maximum pages (nil = unlimited)
  config.window = 4                   # Inner window size
  config.outer_window = 0             # Outer window size
  config.left = 0                     # Left outer window
  config.right = 0                    # Right outer window
  config.page_method_name = :page     # Method name (change if conflicts)
  config.param_name = :page           # URL parameter name
end

Per-Model Configuration

# app/models/post.rb
class Post < ApplicationRecord
  paginates_per 50              # This model shows 50 per page
  max_paginates_per 100         # User can't request more than 100
  max_pages 100                 # Limit to 100 pages total
end

View Helpers

Basic Pagination

<!-- Simple pagination links -->
<%= paginate @posts %>

<!-- With options -->
<%= paginate @posts, window: 2 %>
<%= paginate @posts, outer_window: 1 %>
<%= paginate @posts, left: 1, right: 1 %>

<!-- Custom parameter name -->
<%= paginate @posts, param_name: :pagina %>

<!-- For AJAX/Turbo -->
<%= paginate @posts, remote: true %>

Navigation Links

<!-- Previous/Next links -->
<%= link_to_prev_page @posts, 'Previous', class: 'btn' %>
<%= link_to_next_page @posts, 'Next', class: 'btn' %>

<!-- With custom content -->
<%= link_to_prev_page @posts do %>
  <span aria-hidden="true">&larr;</span> Older
<% end %>

<%= link_to_next_page @posts do %>
  Newer <span aria-hidden="true">&rarr;</span>
<% end %>

Page Info

<!-- Shows: "Displaying posts 1 - 25 of 100 in total" -->
<%= page_entries_info @posts %>

<!-- Custom format -->
<%= page_entries_info @posts, entry_name: 'item' %>

SEO Helpers

<!-- Add rel="next" and rel="prev" link tags to <head> -->
<%= rel_next_prev_link_tags @posts %>

URL Helpers

# Get URLs for navigation
path_to_next_page(@posts)  #=> "/posts?page=3"
path_to_prev_page(@posts)  #=> "/posts?page=1"

Customization

Generating Custom Views

# Generate default theme
rails g kaminari:views default

# Generate with namespace
rails g kaminari:views default --views-prefix admin

# Generate specific theme
rails g kaminari:views bootstrap4

This creates templates in app/views/kaminari/:

  • _first_page.html.erb
  • _prev_page.html.erb
  • _page.html.erb
  • _next_page.html.erb
  • _last_page.html.erb
  • _gap.html.erb
  • _paginator.html.erb

Using Themes

<!-- Default theme -->
<%= paginate @posts %>

<!-- Custom theme -->
<%= paginate @posts, theme: 'my_theme' %>

<!-- Bootstrap theme -->
<%= paginate @posts, theme: 'twitter-bootstrap-4' %>

Custom Pagination Template

<!-- app/views/kaminari/_paginator.html.erb -->
<nav class="pagination" role="navigation" aria-label="Pagination">
  <ul class="pagination-list">
    <%= first_page_tag %>
    <%= prev_page_tag %>

    <% each_page do |page| %>
      <% if page.left_outer? || page.right_outer? || page.inside_window? %>
        <%= page_tag page %>
      <% elsif !page.was_truncated? %>
        <%= gap_tag %>
      <% end %>
    <% end %>

    <%= next_page_tag %>
    <%= last_page_tag %>
  </ul>
</nav>

API Pagination

JSON Response

# app/controllers/api/v1/posts_controller.rb
module Api
  module V1
    class PostsController < ApplicationController
      def index
        @posts = Post.page(params[:page]).per(params[:per_page] || 20)

        render json: {
          posts: @posts.map { |p| PostSerializer.new(p) },
          meta: pagination_meta(@posts)
        }
      end

      private

      def pagination_meta(collection)
        {
          current_page: collection.current_page,
          next_page: collection.next_page,
          prev_page: collection.prev_page,
          total_pages: collection.total_pages,
          total_count: collection.total_count
        }
      end
    end
  end
end

API Response Helper

# app/controllers/concerns/paginatable.rb
module Paginatable
  extend ActiveSupport::Concern

  def paginate(collection)
    collection
      .page(params[:page] || 1)
      .per(params[:per_page] || default_per_page)
  end

  def pagination_links(collection)
    {
      self: request.original_url,
      first: url_for(page: 1),
      prev: collection.prev_page ? url_for(page: collection.prev_page) : nil,
      next: collection.next_page ? url_for(page: collection.next_page) : nil,
      last: url_for(page: collection.total_pages)
    }
  end

  def pagination_meta(collection)
    {
      current_page: collection.current_page,
      total_pages: collection.total_pages,
      total_count: collection.total_count,
      per_page: collection.limit_value
    }
  end

  private

  def default_per_page
    20
  end
end

Performance Optimization

Without Count Query

For very large datasets, skip expensive COUNT queries:

# Controller
def index
  @posts = Post.order(:created_at).page(params[:page]).without_count
end

# View - use simple navigation only
<%= link_to_prev_page @posts, 'Previous' %>
<%= link_to_next_page @posts, 'Next' %>

Note: total_pages, total_count, and numbered page links won't work with without_count.

Eager Loading

# Prevent N+1 queries
@posts = Post.includes(:user, :comments)
             .order(:created_at)
             .page(params[:page])

Caching

# Fragment caching
<% cache ["posts-page", @posts.current_page] do %>
  <%= render @posts %>
  <%= paginate @posts %>
<% end %>

Advanced Features

Paginating Arrays

# Controller
@items = expensive_operation_returning_array
@paginated_items = Kaminari.paginate_array(@items, total_count: @items.count)
                           .page(params[:page])
                           .per(10)

# Or with known total
@paginated_items = Kaminari.paginate_array(
  @items,
  total_count: 145,
  limit: 10,
  offset: (params[:page].to_i - 1) * 10
).page(params[:page]).per(10)

SEO-Friendly URLs

# config/routes.rb
resources :posts do
  get 'page/:page', action: :index, on: :collection
end

# 
Compartilhar X LinkedIn