Modo API de Rails en 2026: API RESTful, serialización y buenas prácticas
Dominar el modo API de Rails con buenas prácticas de diseño RESTful, serialización JSON con Alba y jsonapi-serializer, estrategias de autenticación y manejo de errores en Rails 8.

El modo API de Rails elimina el middleware específico del navegador para entregar un backend ligero y rápido, diseñado a propósito para las API JSON. Con Rails 8.1 y el creciente ecosistema de bibliotecas de serialización, construir API RESTful de calidad de producción nunca ha sido tan fluido.
El modo API de Rails elimina las sesiones, las cookies, las vistas y el middleware del asset pipeline. El resultado: un stack más ligero optimizado para respuestas JSON, ideal para backends móviles, microservicios y SPA desacopladas.
Crear una aplicación Rails 8 solo de API
Crear una aplicación Rails dedicada a API requiere un solo flag. La opción --api configura ApplicationController para que herede de ActionController::API en lugar de ActionController::Base, eliminando más de 15 capas de middleware que no cumplen ningún propósito en un contexto puramente de API.
# Terminal command
rails new order_service --api --database=postgresqlEste comando genera un proyecto sin plantillas de vista, sin compilación de assets ni cookies de sesión. El archivo application.rb resultante incluye config.api_only = true, lo que mantiene el stack de middleware al mínimo.
Para aplicaciones Rails full-stack existentes que necesitan un namespace de API, el enfoque difiere: crear un controlador API base que herede de ActionController::API y montar las rutas de API bajo un namespace versionado.
# app/controllers/api/v1/base_controller.rb
module Api
module V1
class BaseController < ActionController::API
before_action :authenticate_request
private
def authenticate_request
# Token validation logic
end
end
end
endEste patrón mantiene intacta la aplicación full-stack mientras añade una capa de API dedicada.
Diseño de rutas RESTful y estrategias de versionado
Un diseño de rutas RESTful limpio impacta directamente en la usabilidad y mantenibilidad de la API. El DSL de routing de Rails facilita expresar jerarquías de recursos, pero unas pocas convenciones separan las API sólidas de las frágiles.
# config/routes.rb
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
resources :users, only: [:index, :show, :create, :update] do
resources :orders, only: [:index, :show, :create]
end
resources :products, only: [:index, :show] do
collection do
get :search
end
end
resource :session, only: [:create, :destroy]
end
end
endConvenciones clave:
- Versionado por namespace (
/api/v1/) en lugar de versionado por cabecera, por simplicidad y cacheabilidad - Anidamiento superficial limitado a un solo nivel:
/users/:user_id/ordersfunciona, pero/users/:user_id/orders/:order_id/itemsdebería convertirse en/orders/:order_id/items - Recursos singulares para los endpoints que representan la sesión o el perfil del usuario actual
Al retirar una versión de la API, devolver un HTTP 410 Gone con un cuerpo JSON que apunte a la nueva versión en lugar de romper silenciosamente a los clientes.
Serialización JSON: Alba vs. jsonapi-serializer
La serialización determina cómo los objetos ActiveRecord se convierten en JSON. La elección del serializador afecta los tiempos de respuesta, la estructura del payload y la flexibilidad del contrato de la API. Dos bibliotecas dominan el ecosistema Rails en 2026: Alba por su velocidad y simplicidad, y jsonapi-serializer por su cumplimiento de la especificación JSON:API.
Alba: rendimiento sin dependencias
Alba serializa objetos Ruby hasta 10 veces más rápido que las alternativas heredadas como ActiveModel::Serializer. No tiene dependencias, lo que la hace ideal para servicios de API ligeros.
# app/resources/user_resource.rb
class UserResource
include Alba::Resource
root_key :user, :users
attributes :id, :email, :name, :created_at
attribute :full_name do |user|
"#{user.first_name} #{user.last_name}"
end
many :orders, resource: OrderResource
# Conditional attributes based on context
attribute :admin_notes, if: proc { |user, params|
params[:current_user]&.admin?
}
end# app/controllers/api/v1/users_controller.rb
class Api::V1::UsersController < Api::V1::BaseController
def show
user = User.includes(:orders).find(params[:id])
render json: UserResource.new(user, params: { current_user: current_user })
end
def index
users = User.where(active: true).page(params[:page])
render json: UserResource.new(users)
end
endjsonapi-serializer: cumplimiento estricto de la especificación
Cuando los consumidores de la API esperan respuestas con formato JSON:API con las claves data, type, attributes y relationships, jsonapi-serializer (el fork mantenido del fast_jsonapi de Netflix) gestiona el formateo automáticamente.
# app/serializers/user_serializer.rb
class UserSerializer
include JSONAPI::Serializer
set_type :user
set_id :id
attributes :email, :name, :created_at
has_many :orders, serializer: OrderSerializer
# Cache at the serializer level for high-traffic endpoints
cache_options store: Rails.cache, namespace: "jsonapi", expires_in: 1.hour
endLa elección depende del proyecto: Alba para API internas, microservicios y backends móviles donde importa la flexibilidad del payload. jsonapi-serializer para API públicas donde los contratos estandarizados reducen la fricción de integración.
¿Listo para aprobar tus entrevistas de Ruby on Rails?
Practica con nuestros simuladores interactivos, flashcards y tests técnicos.
Patrones de autenticación para API Rails
Rails 8 introdujo un generador de autenticación integrado que andamia autenticación basada en sesiones. Adaptarlo al modo solo de API requiere intercambiar las sesiones por cookies por autenticación basada en tokens. Dos patrones dominan: JWT para arquitecturas sin estado y tokens bearer opacos para una revocación más sencilla.
JWT con tokens de corta duración
# app/services/jwt_service.rb
class JwtService
SECRET = Rails.application.credentials.jwt_secret_key
ALGORITHM = "HS256"
def self.encode(payload, exp: 15.minutes.from_now)
payload[:exp] = exp.to_i
JWT.encode(payload, SECRET, ALGORITHM)
end
def self.decode(token)
body = JWT.decode(token, SECRET, true, algorithm: ALGORITHM).first
HashWithIndifferentAccess.new(body)
rescue JWT::ExpiredSignature, JWT::DecodeError => e
nil
end
end# app/controllers/concerns/jwt_authenticatable.rb
module JwtAuthenticatable
extend ActiveSupport::Concern
included do
before_action :authenticate_request
end
private
def authenticate_request
token = request.headers["Authorization"]&.split(" ")&.last
decoded = JwtService.decode(token)
if decoded
@current_user = User.find_by(id: decoded[:user_id])
end
render json: { error: "Unauthorized" }, status: :unauthorized unless @current_user
end
def current_user
@current_user
end
endLos tokens de acceso de corta duración (15 minutos) combinados con la rotación de refresh tokens ofrecen un equilibrio seguro. El token de acceso permanece sin estado, mientras que los refresh tokens almacenados en la base de datos permiten la revocación al cambiar la contraseña o cerrar sesión.
Tokens bearer opacos
Para API más simples donde una consulta a la base de datos por petición es aceptable, has_secure_token ofrece un enfoque directo:
# app/models/user.rb
class User < ApplicationRecord
has_secure_password
has_secure_token :api_token
def regenerate_api_token!
regenerate_api_token
end
endLos tokens opacos simplifican la revocación (eliminar o regenerar el token) pero requieren una consulta a la base de datos en cada petición autenticada.
Gestión estructurada de errores en toda la API
Las respuestas de error consistentes separan las API profesionales de los prototipos. Un gestor de errores centralizado impide que Rails devuelva páginas de error HTML y garantiza que cada fallo devuelva JSON estructurado.
# app/controllers/concerns/error_handler.rb
module ErrorHandler
extend ActiveSupport::Concern
included do
rescue_from ActiveRecord::RecordNotFound, with: :not_found
rescue_from ActiveRecord::RecordInvalid, with: :unprocessable_entity
rescue_from ActionController::ParameterMissing, with: :bad_request
end
private
def not_found(exception)
render json: {
error: "not_found",
message: "Resource not found",
details: exception.message
}, status: :not_found
end
def unprocessable_entity(exception)
render json: {
error: "validation_failed",
message: "Validation failed",
details: exception.record.errors.full_messages
}, status: :unprocessable_entity
end
def bad_request(exception)
render json: {
error: "bad_request",
message: "Missing required parameter",
details: exception.message
}, status: :bad_request
end
endIncluir este concern en el controlador API base. Cada endpoint devuelve entonces errores JSON predecibles con códigos de estado HTTP apropiados, tipos de error legibles por máquina y mensajes legibles por humanos.
Los controladores de API que usan autenticación basada en tokens deben omitir la verificación CSRF. Añadir skip_before_action :verify_authenticity_token o heredar de ActionController::API, que no incluye el middleware CSRF por defecto.
Paginación y optimización de respuestas
Las consultas sin límite son el camino más rápido hacia la degradación del rendimiento. Cada endpoint de listado debería paginar los resultados y comunicar claramente los metadatos de paginación.
# app/controllers/api/v1/products_controller.rb
class Api::V1::ProductsController < Api::V1::BaseController
def index
products = Product
.where(active: true)
.order(created_at: :desc)
.page(params[:page])
.per(params[:per_page] || 25)
render json: {
data: ProductResource.new(products).serializable_hash,
meta: {
current_page: products.current_page,
total_pages: products.total_pages,
total_count: products.total_count
}
}
end
endMás allá de la paginación, tres optimizaciones marcan una diferencia medible en los tiempos de respuesta de la API:
- El eager loading con
includesopreloadelimina las consultas N+1 que multiplican los viajes de ida y vuelta a la base de datos - Seleccionar solo las columnas necesarias con
.select(:id, :name, :price)cuando los serializadores usan un subconjunto de los atributos del modelo - Las cabeceras de caché HTTP mediante
stale?yfresh_whenpermiten a los clientes y CDN cachear respuestas sin lógica personalizada
Probar endpoints de API Rails con RSpec
Las pruebas de API deberían verificar los códigos de estado, la estructura de la respuesta y las barreras de autenticación. Las request specs en RSpec atraviesan el stack de middleware completo, lo que las convierte en la representación más cercana al comportamiento real de una API.
# spec/requests/api/v1/users_spec.rb
RSpec.describe "Api::V1::Users", type: :request do
let(:user) { create(:user) }
let(:token) { JwtService.encode(user_id: user.id) }
let(:headers) { { "Authorization" => "Bearer #{token}" } }
describe "GET /api/v1/users/:id" do
it "returns the user with correct structure" do
get "/api/v1/users/#{user.id}", headers: headers
expect(response).to have_http_status(:ok)
json = JSON.parse(response.body)
expect(json["user"]).to include(
"id" => user.id,
"email" => user.email,
"name" => user.name
)
end
it "returns 401 without authentication" do
get "/api/v1/users/#{user.id}"
expect(response).to have_http_status(:unauthorized)
end
it "returns 404 for non-existent user" do
get "/api/v1/users/0", headers: headers
expect(response).to have_http_status(:not_found)
json = JSON.parse(response.body)
expect(json["error"]).to eq("not_found")
end
end
endEstas pruebas cubren los tres escenarios que cada endpoint de API debería manejar: la estructura de una respuesta exitosa, la aplicación de la autenticación y el formato de las respuestas de error.
Características de API de Rails 8.1 que vale la pena adoptar
Rails 8.1 (lanzado en octubre de 2025) añade capacidades directamente relevantes para el desarrollo de API:
- Los Continuable Jobs permiten que las tareas en segundo plano de larga duración (importaciones de datos, procesamiento por lotes) se reanuden desde el último punto de control tras despliegues o reinicios, eliminando el trabajo desperdiciado en los pipelines de jobs en segundo plano
- El Structured Event Logging mediante
Rails.event.notify(...)emite eventos consumibles por plataformas APM (Datadog, New Relic) sin código de instrumentación personalizado - Las Deprecated Associations pueden marcarse con los modos
:warn,:raiseo:notify, ayudando a los equipos a eliminar progresivamente las relaciones heredadas en grandes bases de código de API
Estas características reducen el boilerplate en los proyectos de API y mejoran la observabilidad desde el principio. La guía de migración de Rails 8 cubre la ruta de actualización completa.
¡Empieza a practicar!
Pon a prueba tu conocimiento con nuestros simuladores de entrevista y tests técnicos.
Conclusión
- Usar el modo
--apipara servicios de API dedicados para eliminar middleware innecesario y reducir la latencia de respuesta - Elegir un serializador que se ajuste al contrato: Alba para velocidad y flexibilidad, jsonapi-serializer para cumplimiento estricto de JSON:API
- Implementar autenticación por token con JWT de corta duración y rotación de refresh tokens, o tokens bearer opacos para necesidades de revocación más sencillas
- Centralizar la gestión de errores en un concern compartido para que cada endpoint devuelva JSON estructurado con tipos de error consistentes
- Paginar cada endpoint de listado y aplicar eager loading para eliminar las consultas N+1 antes de que lleguen a producción
- Probar con request specs los tres escenarios fundamentales: estructura de éxito, aplicación de autenticación y formato de errores
- Adoptar las características de Rails 8.1 como los continuable jobs y los eventos estructurados para mejorar la fiabilidad y la observabilidad de los servicios de API
¡Empieza a practicar!
Pon a prueba tu conocimiento con nuestros simuladores de entrevista y tests técnicos.
Etiquetas
Compartir
Artículos relacionados

Solid Queue y Solid Cache en Rails 8: Guía completa para entrevistas técnicas 2026
Análisis profundo de Solid Queue y Solid Cache, los componentes por defecto respaldados por base de datos en Rails 8. Arquitectura, configuración, controles de concurrencia y conocimientos clave para entrevistas técnicas en 2026.

Ruby on Rails 8: Nuevas Características y Guía de Migración 2026
Ruby on Rails 8 presenta el Solid Trifecta, un generador de autenticación integrado, Kamal 2 y Propshaft. Este tutorial cubre cada característica principal y detalla la actualización desde Rails 7 paso a paso.

Action Cable y WebSockets en Rails: Guía Completa para Entrevistas Técnicas
Guia completa sobre Action Cable y WebSockets en Ruby on Rails para entrevistas tecnicas. Conexiones, canales, Solid Cable, Turbo Streams, escalabilidad con Redis y testing con ejemplos de codigo.