Paginación en Ruby on Rails con will_paginate y Pagy
Tu listado de artículos empieza con diez y acaba con miles. Cargarlos todos en una página la hace lenta y nadie va a leerla entera.
Paginar es como un libro: el texto completo no cabe en una hoja, así que se reparte en páginas numeradas y el lector salta a la que quiere. En la web, el número de página viaja en la URL (?page=2) y la base de datos solo devuelve los registros de esa página.
Paginación con will_paginate en tres pasos
- Añade la gema.
- Pagina la consulta en el controlador.
- Pinta los enlaces de página en la vista.
1. Añade la gema
En el Gemfile:
gem "will_paginate", "~> 4.0"
Y la instalas:
bundle install
2. Pagina en el controlador
# app/controllers/articles_controller.rb
def index
@articles = Article.publicados.ultimos.paginate(page: params[:page], per_page: 10)
end
pagees la página que pide el usuario. Llega en la URL:http://localhost:3000/articles?page=2. Si no viene, se muestra la primera.per_pagees cuántos registros hay por página. Por defecto son 30.publicadosyultimosson scopes, consultas con nombre definidas en el modelo. Puedes encadenarpaginateantes o después de ellos. Tienes más en Scopes en Ruby on Rails.
Si quieres el mismo tamaño en todo el modelo, fíjalo una vez:
class Article < ApplicationRecord
self.per_page = 10
end
3. Pinta la paginación en la vista
<%# app/views/articles/index.html.erb %>
<% @articles.each do |article| %>
<h2><%= link_to article.title, article %></h2>
<div><%= article.body %></div>
<% end %>
<%= will_paginate @articles %>
will_paginate @articles genera solo los enlaces «anterior», los números de página y «siguiente»:
Salen sin estilos; el README de la gema enlaza unas hojas CSS de ejemplo para darles forma. Si dudas entre <% %> y <%= %> en la vista, lo tienes en Diferencia entre <% %> y <%= %> en Ruby on Rails.
Alternativas actuales: Pagy y Kaminari
Pagy
Pagy tiene desarrollo activo (la serie 43; aquí se ha probado la 43.8.1, de octubre de 2026) y destaca por ser ligera. La idea es la misma, con otra sintaxis:
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
include Pagy::Method
end
# app/controllers/articles_controller.rb
def index
@pagy, @articles = pagy(:offset, Article.publicados.ultimos, limit: 10)
end
<%# app/views/articles/index.html.erb %>
<%== @pagy.series_nav %>
pagy devuelve dos cosas: el objeto con los datos de la paginación (@pagy) y los registros de la página (@articles). series_nav pinta los enlaces; va con <%== %> porque ya devuelve HTML seguro.
series_nav genera un <nav> con enlaces «anterior», números y «siguiente», y marca la página actual con aria-current="page".
Kaminari
Kaminari es la otra gema clásica de paginación en Rails y sigue publicando versiones (la 1.3.3 salió en noviembre de 2026). Su sintaxis encadena métodos:
# Gemfile
gem "kaminari"
# app/controllers/articles_controller.rb
@articles = Article.publicados.ultimos.page(params[:page]).per(10)
<%= paginate @articles %>
No mezcles Kaminari y will_paginate en el mismo proyecto: los dos añaden un método page a los modelos y chocan.
Resumen
| Paso | will_paginate | Pagy 43 | Kaminari |
|---|---|---|---|
| Gema | gem "will_paginate" |
gem "pagy" |
gem "kaminari" |
| Controlador | Article.paginate(page: params[:page], per_page: 10) |
@pagy, @articles = pagy(:offset, Article.all, limit: 10) |
Article.page(params[:page]).per(10) |
| Vista | <%= will_paginate @articles %> |
<%== @pagy.series_nav %> |
<%= paginate @articles %> |
| Estado | Modo mantenimiento | Desarrollo activo | Desarrollo activo |
Fuentes
- README de will_paginate (versión 4.0.1): uso de
paginate,per_pagey aviso de modo mantenimiento. - Documentación de Pagy y su README (serie 43; probado con la 43.8.1).
- README de Kaminari y versión 1.3.3 en RubyGems.
- Ejecutado en Docker con la imagen oficial
ruby:4.0(Ruby 4.0.9), Active Record 8.1.4.1 y SQLite en memoria, con 5 registros y 2 por página:paginatecon scopes (will_paginate 4.0.1,per_pagepor defecto 30),page(2).per(2)(Kaminari 1.3.3, en un script aparte porque choca con will_paginate) ypagy(:offset, …, limit: 2)con el HTML deseries_nav(Pagy 43.8.1). Los helpers de vistawill_paginateypaginatesolo se han comprobado en sus README. La captura es de Rubén, del artículo original.