Hanami 2 y Roda: alternativas a Rails para APIs y proyectos más ligeros en Ruby

Rails domina el ecosistema Ruby para aplicaciones web. Es maduro, tiene una comunidad enorme y el stack que incluye en 2024-2026 (Solid Queue, Hotwire, Kamal) cubre la mayoría de las necesidades. Pero no es la única opción, y hay casos donde sus alternativas tienen ventajas reales. Hanami 2 y Roda son las dos más serias para proyectos que buscan algo diferente.

El argumento contra Rails

Rails sigue el principio de «convention over configuration» con mucha agresividad. Eso es una ventaja cuando trabajas dentro de sus convenciones, pero puede convertirse en obstáculo cuando necesitas salirte de ellas. Rails tiene mucha magia: métodos que aparecen automáticamente, callbacks que se ejecutan sin que los llames explícitamente, un sistema de carga de clases que puede sorprender.

Para APIs de alto rendimiento, la carga de Rails (ActiveRecord, ActionView, todos sus railtie) puede ser excesiva. Para proyectos grandes con equipos que priorizan la explicitad sobre la convención, el modelo de Rails puede no encajar.

Hanami 2: arquitectura explícita

Hanami 2.0 salió en noviembre de 2022 después de una reescritura casi completa respecto a la versión 1. El foco es la separación de responsabilidades y la inyección de dependencias explícita.

# Estructura de un proyecto Hanami 2
mi_app/
  app/
    actions/          # Acciones HTTP (equivalente a controladores Rails)
    repos/            # Repositorios de datos
    views/            # Vistas
    entities/         # Objetos de dominio
  config/
    app.rb            # Configuración principal
    providers/        # Proveedores de servicios (DB, mailer, etc.)
  slices/             # Partes independientes de la app (como engines en Rails)

La inyección de dependencias es automática a través del contenedor de la aplicación:

# app/actions/usuarios/crear.rb
module MiApp
  module Actions
    module Usuarios
      class Crear < MiApp::Action
        include Deps[
          "repos.usuario_repo",
          "servicios.email_verificacion"
        ]

        params do
          required(:nombre).filled(:string)
          required(:email).filled(:string)
        end

        def handle(request, response)
          halt 422, response.render unless request.params.valid?

          usuario = usuario_repo.crear(request.params[:usuario])
          email_verificacion.enviar(usuario)

          response.status = 201
          response.body = usuario.to_json
        end
      end
    end
  end
end

Cada acción es una clase con un método handle. Las dependencias se declaran explícitamente con include Deps[...]. No hay magia: si necesitas el repositorio de usuarios, lo declaras y el contenedor lo inyecta.

Persistencia con ROM (Ruby Object Mapper)

Hanami usa ROM como capa de persistencia en lugar de ActiveRecord. ROM separa las queries de los objetos de dominio:

# app/repos/usuario_repo.rb
class UsuarioRepo < MiApp::DB::Repo
  commands :create, :update, :delete

  def por_email(email)
    usuarios.where(email: email).one
  end

  def activos
    usuarios.where(activo: true).to_a
  end

  private

  def usuarios
    root
  end
end

La diferencia con ActiveRecord: el modelo (entidad) no sabe nada de la base de datos, y el repositorio se encarga de las queries. Es más verboso pero más fácil de testar en aislamiento.

Roda: el micro-framework de la familia

Roda es algo distinto: un micro-framework de routing basado en el árbol de rutas. Es extremadamente rápido y minimalista. Fue creado por Jeremy Evans (también autor de Sequel, el ORM alternativo a ActiveRecord).

# config.ru
require 'roda'

class MiApp < Roda
  plugin :json
  plugin :halt

  route do |r|
    r.root do
      { mensaje: 'Hola desde Roda' }
    end

    r.on 'usuarios' do
      r.is do
        r.get do
          # GET /usuarios
          Usuario.all.map(&:to_hash)
        end

        r.post do
          # POST /usuarios
          datos = JSON.parse(r.body.read)
          usuario = Usuario.create(datos)
          response.status = 201
          usuario.to_hash
        end
      end

      r.on :id do |id|
        usuario = Usuario.find(id: id.to_i)
        r.halt(404, { error: 'No encontrado' }) unless usuario

        r.is do
          r.get { usuario.to_hash }      # GET /usuarios/:id
          r.delete { usuario.destroy; '' } # DELETE /usuarios/:id
        end
      end
    end
  end
end

run MiApp

El routing «en árbol» de Roda significa que las rutas se definen como un árbol de decisiones. Cuando coincide un segmento de la ruta, entra en ese bloque y sigue hacia abajo. Es más eficiente que el routing lineal de Sinatra y más explícito que Rails.

Roda con Sequel: el stack ligero

Roda y Sequel forman un stack muy usado para APIs de alto rendimiento:

# Gemfile
gem 'roda'
gem 'sequel'
gem 'pg'

# config/database.rb
require 'sequel'
DB = Sequel.connect(ENV['DATABASE_URL'])

# models/usuario.rb
class Usuario < Sequel::Model
  plugin :json_serializer
  plugin :validation_helpers

  def validate
    super
    validates_presence [:nombre, :email]
    validates_unique :email
  end
end

Sequel tiene un DSL de queries muy expresivo, sin la magia de ActiveRecord pero con más control sobre el SQL generado.

Cuándo tiene sentido cada uno

Framework

Mejor para

Curva de aprendizaje

Rails 8

Apps completas, equipos con experiencia Rails, prototipado rápido

Media (mucho aprendido por convención)

Hanami 2

Apps grandes con DDD, equipos que priorizan explicitad, microservicios

Alta (hay que aprender ROM, el contenedor, slices)

Roda

APIs de alto rendimiento, micro-servicios, casos donde Rails es excesivo

Baja (es muy simple, pero minimalista)

El estado actual en 2026

Hanami 2 sigue madurando. La comunidad es pequeña comparada con Rails, pero activa. La documentación ha mejorado mucho desde el lanzamiento de 2.0. La versión 2.2 (2024) añadió soporte para Assets y mejoró la integración con Hanami::View.

Roda es quizás el framework Ruby más infrautilizado. Jeremy Evans lo usa como base para muchos de sus proyectos personales y es el framework detrás de varias aplicaciones de producción de alto tráfico. Si necesitas un punto de comparación con el mundo Python, el artículo sobre FastAPI en 2026 muestra cómo el ecosistema Python resuelve el mismo problema de APIs ligeras con rendimiento alto.

Para la mayoría de los proyectos nuevos en Ruby, Rails 8 sigue siendo la primera opción. Pero conocer Hanami y Roda da perspectiva sobre qué decisiones de diseño tomó Rails y cuáles son sus trade-offs. Eso solo mejora el código que escribes con Rails.

Imagen: Pexels / Digital Buggu

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP