“¿Necesitas autenticación, procesamiento en segundo plano, exportación de PDF o facturación de Stripe? Es casi seguro que alguien ha publicado una gema para ello, y esa es exactamente la razón por la que los desarrolladores recurren a las gemas de Rails con tanta frecuencia. También es la razón por la que un Gemfile puede convertirse en una factura de mantenimiento con la que nadie se inscribió.
La escala del ecosistema explica el afecto. RubyGems.org, el registro oficial de gemas de Ruby on Rails y todos los demás paquetes de Ruby, actualmente alberga 193.910 gemas, 244.700 usuarios registrados y casi 255 mil millones de descargas.
De las diez gemas de Ruby más populares de todos los tiempos, las líderes son `bundler` y un grupo de gemas del SDK de AWS, pero tres bibliotecas principales de Rails también figuran en la lista, con `i18n`, `activesupport` y `rake` superando cada una los 1.300 millones de descargas.
Añade una línea a tu Gemfile, ejecuta `bundle install`, y heredas miles de horas de trabajo de las personas que mantienen esas bibliotecas de Ruby. Este artículo es la versión honesta de cómo tratamos esa herencia en Redwerk: las gemas que ejecutamos en producción cuando construimos y mantenemos aplicaciones Ruby on Rails para clientes, las que eliminamos y el criterio que decide cuál es cuál.”
Cada gema de Rails es también un pasivo
Una gema de Rails es una biblioteca empaquetada de código Ruby que insertas en un proyecto para añadir una función sin tener que construirla tú mismo. Cada gema en tu Gemfile es código del que dependes pero que no escribiste, mantenido por personas que nunca has conocido, y capaz de fallar, quedarse obsoleto o volverse hostil. Eso no es paranoia. Es la realidad documentada del software moderno, donde la reutilización es la norma y la superficie de ataque ha crecido junto con ella.
Los datos lo respaldan. En agosto de 2025, los investigadores descubrieron una campaña de 60 gemas maliciosas que se hacían pasar por herramientas de automatización de redes sociales, activas desde al menos marzo de 2023 y descargadas más de 275.000 veces antes de ser retiradas. Mantener el registro en sí tampoco es gratis, ya que Ruby Central estima que ejecutar RubyGems.org, incluyendo servidores, infraestructura y mantenedores remunerados, cuesta alrededor de 500.000 dólares al mes. Nada de esto significa que las gemas sean malas. Significa que cada una es una decisión, y las decisiones merecen un proceso.
Cómo decidimos si una gema se gana su lugar
La mayoría de los artículos mencionan la intuición aquí, pero la intuición no se transfiere a un equipo ni se explica a un cliente. Antes de que una gema entre en un Gemfile, la pasamos por una breve lista de verificación. El objetivo no es minimizar la cantidad de gemas por sí mismo. Es asegurarse de que cada dependencia esté pagando su alquiler.
- Señales de mantenimiento: cadencia de lanzamiento, la proporción de problemas abiertos frente a cerrados y el riesgo del factor autobús. Una gema ingeniosa con un único mantenedor y un año de silencio sigue siendo un riesgo.
- Peso y huella transitiva: una gema arrastra sus propias dependencias, y tú las heredas todas, así que comprobamos qué llega aguas abajo antes de comprometernos.
- La prueba de “¿Rails ya hace esto?”: nos inclinamos por Rails, aburrido y estándar, y si el framework lo cubre, usamos el framework.
- Reversibilidad: si la gema se abandona mañana, ¿qué tan difícil es eliminarla? Valoramos el bloqueo por adelantado.
- Licencia y presupuesto: los niveles gratuitos frente a los de pago importan cuando un cliente está controlando el gasto.
- Postura de seguridad: lanzamientos firmados, un mantenedor receptivo y un historial limpio.
- Ajuste con el equipo: los desarrolladores que hereden la aplicación tienen que vivir con nuestras decisiones.
Nuestra regla de trabajo es simple: si nadie en el equipo puede explicar por qué una gema está en el Gemfile, no debería estar allí.
No existe un Gemfile único y correcto
La lista de gemas correcta depende del proyecto que tengas delante, algo que las listas genéricas nunca admiten. Una agencia se enfrenta a esto constantemente, porque nos movemos entre nuevas construcciones, bases de código de una década de antigüedad y todo lo intermedio. No existe una lista universal de gemas de Ruby on Rails que se adapte a todas las situaciones.
- En las nuevas construcciones, nos basamos en las opciones predeterminadas modernas de Rails y una infraestructura adicional mínima.
- En aplicaciones heredadas o antiguas, auditamos antes de añadir, minimizamos el cambio y respetamos los patrones existentes.
- Para clientes con conciencia del presupuesto, evitamos los niveles de gemas de pago y los servicios adicionales cuando una opción basada en base de datos cumple la función.
- Para clientes con requisitos de cumplimiento estrictos, reforzamos las herramientas de seguridad y mantenemos las políticas de actualización conservadoras.
Mismo framework, diferente Gemfile, dependiendo del proyecto.
La base: Servidor, base de datos y trabajos en segundo plano
Algunas decisiones no merecen debate. Para el servidor web usamos Puma, y para la base de datos usamos PostgreSQL, y en una compilación típica de cliente, ninguna de estas decisiones genera mucha discusión. La llamada realmente interesante reside en los trabajos en segundo plano.
Con Rails 8, el procesamiento en segundo plano se convirtió en una verdadera bifurcación en el camino. Active Job es la abstracción de colas del framework, y la pregunta práctica es qué adaptador se sitúa detrás de ella. La decisión `activejob` vs `sidekiq` vs `solid_queue` suele depender de la infraestructura y la escala, más que de la sintaxis.
El compromiso entre `solid_queue` y `sidekiq` es el quid de la cuestión. `Solid Queue` se envía como valor predeterminado de Rails 8 y almacena trabajos en tu base de datos existente utilizando una característica de bloqueo de Postgres y MySQL llamada `FOR UPDATE SKIP LOCKED`, por lo que no necesita Redis ni ningún servicio adicional. Esto te proporciona integridad transaccional, donde un trabajo y los datos en los que se basa se confirman juntos, además de operaciones más sencillas. `Sidekiq` se basa en Redis, está probado en batalla y sigue siendo el campeón de rendimiento una vez que superas unos miles de trabajos por minuto. Si haces la comparación al revés, la lógica de `sidekiq` vs `solid_queue` es idéntica: sopesas el coste de infraestructura adicional y el riesgo transaccional de un almacén separado frente a la velocidad bruta.
Para la mayoría de las aplicaciones de clientes que procesan menos de mil trabajos por minuto, `Solid Queue` es la opción predeterminada correcta y una cosa menos que operar. Cuando un producto realmente funciona a escala, Redis demuestra su valía. Cuando reconstruimos el bot de Slack de PlusPlus, la versión original de Python cedió bajo la carga, así que lo rediseñamos en Ruby on Rails con Redis, PostgreSQL y AWS, y ahora maneja más de un millón de acciones de usuario por minuto. Esa es la escala en la que la infraestructura más pesada se paga claramente por sí misma.
La capa de datos: Extensiones de Active Record
Las gemas en Ruby on Rails que tocan tu capa de datos merecen un escrutinio adicional, porque están cerca de todo. La mayoría de las aplicaciones necesitan el mismo puñado de funciones: paginación, eliminación lógica, búsqueda de texto completo, agrupación por tiempo y modelado JSONB. Durante años, eso significó recurrir a una gema por instinto.
Emparejamos cada necesidad con un candidato. `Pagy` es ligero y rápido para la paginación. `Pg_search` se basa en PostgreSQL en lugar de conectar un clúster de Elasticsearch que aún no necesitas. `Groupdate` ahorra tiempo real cuando agrupas registros por día, semana o mes.
Sin embargo, probablemente no necesites una gema para esto. La eliminación lógica es el ejemplo clásico, ya que una marca de tiempo `deleted_at` y un alcance predeterminado manejan la mayoría de los casos sin una dependencia, y omitir la gema evita los errores sutiles por los que son conocidas las bibliotecas de eliminación lógica. Active Record moderno también modela columnas JSONB de forma nativa, así que recurre a una extensión solo cuando tus consultas realmente superan las funcionalidades integradas.
Autenticación y autorización
Los lectores confunden estas dos cosas constantemente, por lo que es útil separarlas claramente. La autenticación es probar quién es un usuario. La autorización es decidir qué puede hacer ese usuario una vez que está dentro. Requieren herramientas diferentes, y el panorama para la primera ha cambiado recientemente.
Rails 8 incluyó un generador de autenticación integrado que crea plantillas para sesiones, manejo de contraseñas y flujos de restablecimiento sin una gema. Para una compilación de cliente sencilla, ese generador nativo es ahora nuestro punto de partida, y elimina una dependencia pesada que solíamos añadir de forma automática. `Devise` todavía se gana su lugar cuando un proyecto necesita su maduro ecosistema de extensiones, como cuentas confirmables, inicios de sesión bloqueables o múltiples proveedores de OmniAuth, donde reconstruir a mano costaría más que la dependencia.
Para la autorización, nos estandarizamos en `Pundit`, que mantiene la lógica de permisos en objetos de política de Ruby plano que un nuevo desarrollador puede leer en minutos. Las políticas claras y comprobables importan mucho más en una aplicación que devolvemos a un equipo de cliente que cualquier lenguaje de consulta ingenioso.
Frontend y Vistas
El frontend es la verdadera bifurcación en el camino, y elegimos basándonos en el equipo y el producto del cliente, no en la moda. Existen dos caminos genuinamente buenos, y el equivocado crea años de fricción. Elegir bien aquí se trata principalmente de quién mantendrá la aplicación a continuación.
`Hotwire` te mantiene dentro de Rails, envía menos JavaScript y se adapta a aplicaciones centradas en el contenido y con muchas operaciones CRUD que un equipo de Rails poseerá. `Inertia` con `React` tiene sentido cuando el producto es muy interactivo, o cuando el cliente ya tiene desarrolladores de `React` que se encargarán del frontend.
Para la estructura de vistas usamos `ViewComponent` para mantener el marcado comprobable y reutilizable, lo que beneficia a quien herede la base de código. En el pipeline de activos, Rails 8 favorece a `Propshaft` sobre la configuración anterior de `Sprockets`, y para la mayoría de las nuevas compilaciones seguimos esa opción predeterminada. El principio rector es la mantenibilidad para el equipo que convivirá con la aplicación después de que nos vayamos.
Creación de APIs
La mayoría de las aplicaciones de clientes exponen una API en algún momento, y las opciones allí equilibran familiaridad frente a rendimiento. Los valores predeterminados están bien hasta que no lo están, y saber cuándo cambiar es la habilidad. Intentamos no optimizar para un problema que la aplicación aún no tiene.
Para la serialización JSON, normalmente empezamos con `Active Model Serializers` o `Blueprinter`, y pasamos a una opción más rápida como `Alba` solo cuando el perfilado muestra que la serialización es el cuello de botella real. Tratamos las API REST como si estuvieran orientadas a la documentación, generando una especificación OpenAPI para que otros equipos del cliente puedan integrarse sin necesidad de hacer ingeniería inversa de nuestros controladores. Esa disciplina demostró su valor en Cleanagents, una aplicación bajo demanda para limpiadores autónomos en Alemania y Austria, donde la plataforma existente no exponía ninguna API. Construimos APIs RESTful en Rails para comunicarnos con la aplicación Android, utilizamos la gema `Geocoder` para resolver las coordenadas de los pedidos y enviamos esa geocodificación a un proceso en segundo plano para que la aplicación se mantuviera receptiva.
`GraphQL` tiene un lugar real cuando un cliente tiene muchos consumidores con diferentes necesidades de datos, como varios frontends que acceden a un backend. Para una sola aplicación con puntos finales predecibles, normalmente añade complejidad de esquema y dolores de cabeza de caché que una simple API REST habría evitado. La recomendamos cuando el producto lo requiere, y disuadimos a los clientes de usarla cuando no es así.
Funciones de IA: La realidad de 2026
Muchos productos ahora quieren un modelo de lenguaje en algún lugar de la pila, y Rails se ha puesto al día. Gemas como `ruby-openai` y la más nueva `RubyLLM` hacen que llamar a un modelo y obtener una salida estructurada sea realmente práctico. Emparejar esas con un enfoque de salida tipificada mantiene las respuestas lo suficientemente predecibles como para almacenarlas y actuar sobre ellas.
La advertencia que la mayoría de los artículos omiten es la importante. No añadas dependencias de IA a un producto que no las necesita, y pasa cada gema de IA por el mismo criterio que cualquier otra dependencia. El riesgo no es teórico. En las pruebas de Sonatype, el 27,8% de las recomendaciones de actualización de dependencias de un LLM hacían referencia a versiones que nunca se publicaron, y algunas apuntaban a paquetes genuinamente comprometidos. Un agente de codificación de IA que recomienda con confianza una gema alucinada es precisamente el momento de volver a las opciones aburridas y verificadas.
Observabilidad, registro y seguridad en producción
Para las aplicaciones que mantenemos, algunas categorías no son opcionales. El registro estructurado con `Lograge`, métricas básicas y seguimiento de errores a través de algo como `Sentry` marcan la diferencia entre resolver un incidente en minutos y adivinar en la oscuridad. Estas gemas se ganan su lugar precisamente porque solo te das cuenta de ellas cuando faltan.
La auditoría de dependencias pertenece al pipeline, no a la memoria de alguien. Ejecutamos `bundler-audit` para señalar gemas con vulnerabilidades conocidas y `Brakeman` para análisis estático de seguridad, ambos integrados en CI para que una dependencia arriesgada falle la compilación en lugar de llegar a producción. Esto es más importante para una agencia que envía a clientes que para un proyecto secundario individual, y es uno de los elementos de nuestra lista de verificación de revisión de código de Ruby on Rails que tratamos como no negociables.
Experiencia del desarrollador y pruebas
La cultura de pruebas realmente se trata de la calidad de la aplicación después de que finaliza nuestra participación. Nos estandarizamos en `RSpec` con `FactoryBot` para las fixtures, `Capybara` para pruebas de sistema y navegador, y un perfilador cuando necesitamos encontrar dónde va realmente el tiempo. El objetivo es una suite en la que el propio equipo del cliente pueda confiar y ampliar.
Usamos `Bullet` para detectar consultas N+1 en desarrollo antes de que se conviertan en ralentizaciones en producción, porque nada erosiona más la confianza en una base de código heredada que una página que carga lentamente sin una razón obvia. Una buena cobertura y patrones de consulta limpios son lo que hacen que una entrega sea una entrega real en lugar de una despedida y buena suerte. Esa mantenibilidad es el resultado real.
Mantener un Gemfile saludable a lo largo de los años
La parte del trabajo que define el trabajo de una agencia es mantener un Gemfile saludable mucho después del lanzamiento. Tratamos el mantenimiento como una rutina en lugar de una misión de rescate, porque las actualizaciones pequeñas y frecuentes son mucho más baratas que el salto de versión una vez cada tres años que se convierte en una migración de varias semanas. En la práctica, eso significa algunos hábitos permanentes:
- Auditar según un calendario: revisamos las dependencias en una cadencia establecida en lugar de esperar a que algo se rompa, ejecutando `bundle outdated` y `bundler-audit` en CI para que las gemas obsoletas y las vulnerabilidades conocidas aparezcan en cada compilación.
- Actualizar en pequeños pasos: las versiones de parche y menores se aplican a un ritmo regular, y las versiones principales se planifican deliberadamente leyendo primero el registro de cambios, de modo que ninguna actualización sea una sorpresa.
- Automatizar el trabajo pesado: herramientas como `Dependabot` o `Renovate` abren solicitudes de extracción de actualizaciones por nosotros, lo que mantiene el backlog visible y las diferencias lo suficientemente pequeñas como para revisarlas.
- Vigilar el abandono: señalamos las gemas con un solo mantenedor o un largo silencio, y luego las reemplazamos a propósito antes de que una dependencia no mantenida bloquee una actualización de Rails o Ruby.
- Mantener Ruby y Rails actualizados: permanecer en versiones compatibles del framework y del lenguaje evita los callejones sin salida de seguridad y compatibilidad que provienen de las versiones de fin de vida útil.
- Podar lo que nadie puede justificar: cada auditoría es también una oportunidad para eliminar gemas que nadie puede explicar, lo que reduce la superficie de ataque y la carga de mantenimiento al mismo tiempo.
- Apoyarse en la suite de pruebas: una cobertura sólida es lo que hace que todo lo anterior sea seguro, ya que nos permite actualizar con confianza en lugar de esperar.
En aplicaciones de clientes heredadas, esta disciplina es donde se muestra el beneficio. Las aplicaciones que son agradables de mantener cinco años después son aquellas en las que alguien mantuvo honesto el Gemfile, y ese trabajo importa mucho más con el tiempo de lo que jamás se muestra en una demostración de funciones.
Construye con un equipo que realmente lanza Rails
Un buen Gemfile es un signo de juicio de ingeniería, y el juicio es lo que realmente contratas cuando contratas a una agencia. En Redwerk hemos pasado años construyendo y manteniendo aplicaciones Rails donde las decisiones de dependencia tuvieron consecuencias reales. Los estudios de caso cuentan esa historia mejor que cualquier lista de características.
Reconstruimos el bot de Slack PlusPlus de un prototipo de Python que no podía escalar a un sistema Rails que maneja más de un millón de acciones por minuto. Construimos el backend y las API RESTful para Cleanagents para que una aplicación Android pudiera servir a limpiadores autónomos en Alemania y Austria. Y en Adfectious, una plataforma de publicidad móvil, diseñamos la arquitectura y un motor de procesamiento de banners, con código de instalación entregado en Ruby on Rails, PHP, ASP, C# y JSP. Si estás iniciando una nueva compilación de Rails, o te preguntas si tu Gemfile actual te está ayudando o costando, contáctanos y echaremos un vistazo.
Vea cómo utilizamos Ruby on Rails y gemas como Geocoder para lanzar Cleanagents, una plataforma de limpieza bajo demanda adquirida posteriormente por Helpling.de