# 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. - Published: 2026-06-12 - Updated: 2026-06-17 - Author: SharpSkill - Tags: ruby-on-rails, api, rest, serialization, best-practices - Reading time: 9 min --- 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. > **Lo esencial** > > 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. ```ruby # Terminal command rails new order_service --api --database=postgresql ``` Este 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. ```ruby # 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 end ``` Este 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](https://guides.rubyonrails.org/routing.html) 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. ```ruby # 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 end ``` Convenciones 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/orders` funciona, pero `/users/:user_id/orders/:order_id/items` debería convertirse en `/orders/:order_id/items` - **Recursos singulares** para los endpoints que representan la sesión o el perfil del usuario actual > **Deprecación de versiones** > > 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](https://okuramasafumi.github.io/alba/) por su velocidad y simplicidad, y [jsonapi-serializer](https://github.com/jsonapi-serializer/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. ```ruby # 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 ``` ```ruby # 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 end ``` ### jsonapi-serializer: cumplimiento estricto de la especificación Cuando los consumidores de la API esperan respuestas con formato [JSON:API](https://jsonapi.org/) con las claves `data`, `type`, `attributes` y `relationships`, `jsonapi-serializer` (el fork mantenido del fast_jsonapi de Netflix) gestiona el formateo automáticamente. ```ruby # 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 end ``` La 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. ## Patrones de autenticación para API Rails Rails 8 introdujo un [generador de autenticación](https://guides.rubyonrails.org/security.html) 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 ```ruby # 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 ``` ```ruby # 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 end ``` Los 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: ```ruby # app/models/user.rb class User < ApplicationRecord has_secure_password has_secure_token :api_token def regenerate_api_token! regenerate_api_token end end ``` Los 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. ```ruby # 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 end ``` Incluir 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. > **Omitir CSRF para la autenticación por token** > > 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. ```ruby # 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 end ``` Más allá de la paginación, tres optimizaciones marcan una diferencia medible en los tiempos de respuesta de la API: - **El eager loading** con `includes` o `preload` elimina las [consultas N+1](/blog/ruby-on-rails/activerecord-fixing-n-plus-1-query-problems) 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?` y `fresh_when` permiten 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](https://guides.rubyonrails.org/testing.html) 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. ```ruby # 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 end ``` Estas 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](/technologies/ruby-on-rails/interview-questions/active-job-background-jobs) - **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`, `:raise` o `: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](/blog/ruby-on-rails/ruby-on-rails-8-new-features-migration-guide) cubre la ruta de actualización completa. ## Conclusión - **Usar el modo `--api`** para 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 --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/es/blog/ruby-on-rails/rails-api-mode-restful-serialization-best-practices