Ruby Framework

Ruby on Rails

Rails es el framework full-stack de Ruby basado en la convención sobre la configuración. Decide las partes aburridas —nombres de archivos, nombres de tablas, rutas— para que puedas dedicar tu tiempo al producto.

intermediate15 min readUpdated 16 sept 2026
app/controllers/posts_controller.rb
ruby
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
  before_action :set_post, only: %i[show update destroy]

  def index
    @posts = Post.includes(:author).published.recent
  end

  def create
    @post = Current.user.posts.build(post_params)
    if @post.save
      redirect_to @post, notice: "Post created"
    else
      render :new, status: :unprocessable_entity
    end
  end

  private

  def set_post
    @post = Post.find(params[:id])
  end

  def post_params
    params.require(:post).permit(:title, :body)
  end
end
Lanzado
2004
Creado por
David Heinemeier Hansson
Lenguaje
Ruby
Estilo
Convention over configuration
Capa de datos
Active Record ORM
Versión
8.x

Por que importa

Por qué Rails es tan rápido para desarrollar

CRUD en una tarde

Los generadores, las migraciones y el scaffolding convierten un modelo de datos en una aplicación funcional respaldada por una base de datos en horas en lugar de semanas.

Convención sobre configuración

Valores predeterminados sensatos deciden los nombres de archivos, nombres de tablas y rutas. Solo los sobrescribes cuando tu dominio realmente necesita algo diferente.

Gems para todo

La autenticación, los pagos, la subida de archivos, la búsqueda y los paneles de administración cuentan con gems maduras y probadas en batalla, mantenidas por la comunidad.

La imagen completa

MVC, convenciones, gems

Rails le da a cada solicitud la misma estructura: una ruta, un controlador, un modelo y una vista, nombrados de la manera que el framework ya espera.

Convención sobre configuración

Decidir

El framework toma la decisión predeterminada para que tú no tengas que hacerlo. Un modelo Post se mapea a una tabla posts y a una ruta /posts sin configuración.

Active Record

Persistir

Los modelos envuelven las tablas de la base de datos con asociaciones, validaciones, scopes y migraciones, manteniendo el SQL fuera de tu código diario.

Recursos RESTful

Exponer

resources :posts declara las siete rutas CRUD convencionales, y los controladores siguen las mismas acciones para cada recurso.

HTML5 de un vistazo

La caja de herramientas de Rails

Rutas RESTful

resources :posts te proporciona index, show, new, create, edit, update y destroy.

Active Record

Los modelos, las asociaciones y las migraciones describen tu esquema en Ruby.

MVC

Los controladores coordinan, los modelos contienen el dominio y las vistas renderizan la respuesta.

Generadores

rails generate escribe modelos, controladores, migraciones y tests por ti.

Hotwire

Turbo y Stimulus añaden interactividad sin necesidad de una SPA separada.

Background jobs

Active Job junto con Sidekiq ejecuta tareas lentas fuera del ciclo de la solicitud.

Una breve historia

Dos décadas del estilo Rails

  1. 2004

    Rails es extraído de Basecamp

    David Heinemeier Hansson extrae un framework del código base de Basecamp y lo lanza como código abierto.

    04
  2. 2005

    Rails 1.0

    El primer lanzamiento estable convierte la convención sobre la configuración en una idea predominante en el desarrollo web.

    05
  3. 2008

    Rails 2

    REST se convierte en el estilo de enrutamiento predeterminado y los recursos dan forma a cada controlador.

    08
  4. 2010

    Rails 3 y Bundler

    Una API más limpia, Bundler para las dependencias y la fusión con Merb modernizan el stack.

    10
  5. 2016

    Rails 5 y Action Cable

    Los WebSockets llegan al núcleo y el modo API-only se orienta a front-ends de página única.

    16
  6. 2021

    Rails 7 y Hotwire

    Turbo y Stimulus reemplazan a Turbolinks, y los import maps permiten enviar JavaScript sin un bundler.

    21
  7. 2024

    Rails 8

    Solid Queue, Solid Cache y Solid Cable se ejecutan sobre la base de datos, y Kamal simplifica el despliegue.

    24

La guia completa

Ruby on Rails: Todo lo que necesitas saber

¿Qué es Ruby on Rails?

Rails es un framework web full-stack para Ruby. Incluye todo lo que necesita una aplicación web respaldada por una base de datos: un ORM, un router, una capa de vistas, jobs en segundo plano, mailers, caching, WebSockets y un entorno de pruebas. En lugar de elegir y conectar cada una de estas piezas por tu cuenta, heredas un stack coherente diseñado para trabajar en conjunto.

Su idea fundamental es la convención sobre la configuración. El framework asume una estructura lógica — Post vive en app/models/post.rb, se mapea a una tabla de posts y es servido por PostsController — y solo escribes configuración cuando te desvías de ella. El equipo de Rails llama a esta filosofía omakase, la elección del chef: confía en los valores predeterminados y avanzarás más rápido.

Ese intercambio es la razón por la cual Rails ha impulsado productos desde Basecamp y GitHub hasta Shopify y HEY durante veinte años, y por la cual un solo desarrollador aún puede lanzar una aplicación seria en un fin de semana.

Convención sobre configuración

Todos los proyectos de Rails tienen el mismo esqueleto, por lo que nunca tienes que preguntarte dónde va cada cosa.

app/
├── controllers/    # request handling
├── models/         # domain and persistence
├── views/          # templates
├── jobs/           # background work
├── mailers/        # email
└── javascript/     # Stimulus controllers
config/
├── routes.rb       # the URL map
└── database.yml    # connection settings
db/
└── migrate/        # schema history

La recompensa es la predictibilidad. Un desarrollador nuevo abre el repositorio y ya sabe que el modelo User está en app/models/user.rb y que su tabla es users. El nombrado no es un debate de estilo; es una interfaz de la que depende el framework.

El ciclo de peticiones MVC

Rails es un framework Model-View-Controller, y cada petición HTTP sigue el mismo camino:

  1. El Routing asocia la URL con una acción del controlador.
  2. El controller carga o modifica datos a través de los modelos.
  3. Los Models aplican las reglas de dominio y se comunican con la base de datos.
  4. Una view renderiza la respuesta, generalmente como HTML.
# config/routes.rb
Rails.application.routes.draw do
  resources :posts
  root "posts#index"
end

Una petición a GET /posts llega a PostsController#index, que prepara @posts, tras lo cual se renderiza app/views/posts/index.html.erb. Mantener cada capa enfocada en su responsabilidad es lo que permite que una aplicación de Rails sea mantenible a medida que crece.

La línea de comandos es el framework

Casi no interactúas con Rails a través de archivos de configuración. La mayor parte del trabajo ocurre en la terminal.

rails new shop --database=postgresql
cd shop

bin/rails generate scaffold Post title:string body:text published:boolean
bin/rails generate model Comment post:references body:text
bin/rails generate controller Pages home about

bin/rails db:create db:migrate
bin/rails server

generate escribe por ti el modelo, la migración, el controlador, las rutas, las vistas y los tests, y la salida del generador te indica qué ha cambiado. Lee cada archivo generado antes de conservarlo; la forma más rápida de aprender Rails es estudiar lo que escribe y luego borrar lo que no necesites.

Active Record: la capa de modelo

Active Record es el ORM. Una clase de modelo envuelve una tabla de la base de datos, y una instancia envuelve una fila.

Migraciones

Las migraciones son cambios de esquema versionados y reversibles almacenados en db/migrate. Son la única forma soportada de modificar la base de datos.

class CreatePosts < ActiveRecord::Migration[8.0]
  def change
    create_table :posts do |t|
      t.string :title, null: false
      t.text :body, null: false
      t.boolean :published, default: false, null: false
      t.references :author, null: false, foreign_key: { to_table: :users }
      t.timestamps
    end

    add_index :posts, %i[published created_at]
  end
end

Ejecuta bin/rails db:migrate para aplicarla y bin/rails db:rollback para deshacerla. Debido a que change es reversible, Rails sabe cómo revertir las operaciones sin que tengas que escribir un método down.

Asociaciones

Las asociaciones describen relaciones y generan métodos convenientes.

class User < ApplicationRecord
  has_many :posts, dependent: :destroy
  has_many :comments, through: :posts
end

class Post < ApplicationRecord
  belongs_to :author, class_name: "User", inverse_of: :posts
  has_many :comments, dependent: :destroy
  has_one_attached :cover
end

Con esto configurado, user.posts, post.author y post.comments.create(body: "...") funcionan, y dependent: :destroy evita que queden filas huérfanas en la base de datos.

Validaciones y scopes

Las validaciones protegen el dominio en la capa de modelo, por donde pasa cada escritura.

class Post < ApplicationRecord
  validates :title, presence: true, length: { maximum: 120 }
  validates :body, presence: true
  validates :slug, uniqueness: true

  scope :published, -> { where(published: true) }
  scope :recent, -> { order(created_at: :desc) }

  before_validation :generate_slug, on: :create

  private

  def generate_slug
    self.slug ||= title.to_s.parameterize
  end
end

Los scopes devuelven relaciones, por lo que se pueden componer: Post.published.recent.limit(20) se lee como una frase y se ejecuta como una sola consulta. Cuando un scope supere una o dos líneas, conviértelo en un método de clase para que siga siendo legible.

Evitando consultas N+1

El problema de rendimiento más común en Rails es la consulta N+1: una consulta para obtener una lista y luego una consulta más por cada asociación de cada fila.

# Two queries total, no matter how many posts.
posts = Post.includes(:author, :comments).recent

posts.each do |post|
  puts "#{post.title} by #{post.author.name}"
end

Usa includes cuando vayas a acceder a la asociación, preload cuando quieras una consulta separada, y eager_load cuando también filtres por la asociación. Añade la gema bullet al entorno de development y marcará cada N+1 antes de que llegue a producción.

Controladores y rutas RESTful

resources declara las rutas CRUD convencionales y las mapea a acciones del controlador con nombres coincidentes.

# config/routes.rb
Rails.application.routes.draw do
  resources :posts do
    resources :comments, only: %i[index create destroy]
  end

  namespace :api do
    namespace :v1 do
      resources :posts, only: %i[index show create update destroy]
    end
  end
end

Los controladores deben permanecer ligeros. Se encargan de cargar datos, llamar al dominio y elegir una respuesta. La lógica de negocio pertenece a los modelos o a los objetos de servicio, no a las acciones.

class PostsController < ApplicationController
  before_action :set_post, only: %i[show update destroy]

  def index
    @posts = Post.published.includes(:author).recent
  end

  def create
    @post = Post.new(post_params)
    if @post.save
      redirect_to @post, notice: "Post created."
    else
      render :new, status: :unprocessable_entity
    end
  end

  private

  def set_post
    @post = Post.find(params[:id])
  end

  def post_params
    params.require(:post).permit(:title, :body, :published, tag_ids: [])
  end
end

Los strong parameters no son opcionales. params.require(:post).permit(...) es la barrera que evita que un cliente modifique columnas que nunca tuviste la intención de exponer, como admin o role.

Vistas, ERB y layouts

Las vistas son plantillas ERB: HTML con Ruby embebido. Rails escapa la salida por defecto, lo que elimina toda una categoría de errores de cross-site scripting.

<%# app/views/posts/index.html.erb %>
<h1>Posts</h1>

<%= link_to "New post", new_post_path %>

<ul>
  <% @posts.each do |post| %>
    <li>
      <%= link_to post.title, post %>
      <span><%= pluralize(post.comments.size, "comment") %></span>
    </li>
  <% end %>
</ul>

Usa <%= %> para imprimir contenido y <% %> para ejecutar código sin imprimir. Un layout en app/views/layouts/application.html.erb envuelve cada página, y los partials —archivos que comienzan con un guion bajo— permiten reutilizar el marcado mediante render "post", post: post o simplemente render @posts.

Hotwire: Turbo y Stimulus

El Rails moderno añade interactividad sin necesidad de una single-page app. Turbo intercepta los enlaces y formularios para intercambiar fragmentos de página a través de la red; Stimulus añade pequeños comportamientos de JavaScript donde realmente son necesarios.

<%# Turbo Frames scope an update to one part of the page %>
<%= turbo_frame_tag "comments" do %>
  <%= render @post.comments %>
<% end %>
// app/javascript/controllers/dropdown_controller.js
import { Controller } from "@hotwired/stimulus";

export default class extends Controller {
  static targets = ["menu"];

  toggle() {
    this.menuTarget.classList.toggle("hidden");
  }
}

Esto es mejora progresiva en la práctica: el HTML renderizado en el servidor es la base, y JavaScript lo mejora. La mayoría de las apps de Rails nunca necesitan un router en el lado del cliente.

Assets y import maps

Rails 7 reemplazó el antiguo pipeline de Sprockets por import maps de forma predeterminada y ofrece Propshaft como un asset pipeline más sencillo. Puedes anclar una librería sin necesidad de un paso de compilación con Node.

bin/importmap pin local-time
bin/rails assets:precompile

Si prefieres un bundler, bin/rails javascript:install:esbuild o :vite cambian la configuración. El principio es el mismo: servir lo que el navegador entiende y mantener la toolchain fuera del camino hasta que sea necesaria.

Tareas en segundo plano (Background jobs)

Cualquier proceso lento —enviar un correo electrónico, llamar a una API, generar un reporte— debe ir en un job, no en la solicitud. Active Job es la interfaz común; el adaptador decide dónde se ejecutan los jobs.

class PublishPostJob < ApplicationJob
  queue_as :default

  retry_on Net::ReadTimeout, wait: :polynomially_longer, attempts: 5

  def perform(post_id)
    Post.find(post_id).publish!
  end
end

PublishPostJob.perform_later(post.id)
# config/application.rb
config.active_job.queue_adapter = :solid_queue # or :sidekiq

Rails 8 incluye Solid Queue, que mantiene los jobs en la base de datos y no requiere Redis, por lo que una aplicación de un solo servidor tiene una pieza móvil menos. Sidekiq sigue siendo una opción sólida para volúmenes altos de datos.

Pruebas

Rails genera pruebas para todo lo que crea. Minitest viene incluido por defecto y es rápido; RSpec es la alternativa popular con una sintaxis más expresiva.

# test/models/post_test.rb
require "test_helper"

class PostTest < ActiveSupport::TestCase
  test "requires a title" do
    post = Post.new(body: "Hello")
    assert_not post.valid?
    assert_includes post.errors[:title], "can't be blank"
  end
end
# spec/models/post_spec.rb
RSpec.describe Post, type: :model do
  it "is invalid without a title" do
    expect(Post.new(body: "Hello")).not_to be_valid
  end
end

Las pruebas de controlador realizan solicitudes reales en el mismo proceso, lo que permite detectar errores de enrutamiento y de parámetros que las pruebas unitarias pasan por alto.

# test/controllers/posts_controller_test.rb
class PostsControllerTest < ActionDispatch::IntegrationTest
  test "lists published posts" do
    Post.create!(title: "Hi", body: "There", published: true)
    get posts_url
    assert_response :success
  end
end

Ejecuta todo con bin/rails test o bundle exec rspec. Añade bin/rails test:system para pruebas de sistema basadas en el navegador cuando un flujo sea lo suficientemente importante como para probarlo de extremo a extremo.

La consola de Rails

bin/rails console inicia tu aplicación con todos los modelos y helpers disponibles. Es la forma más rápida de explorar datos, probar una consulta y reproducir un error.

bin/rails console
bin/rails console --sandbox   # rolls back all changes on exit
Post.published.recent.limit(5)
Post.where(published: false).update_all(published: true)
Post.includes(:author).find_each { |post| puts post.title }

--sandbox es una red de seguridad mientras experimentas: cualquier escritura se revierte al salir.

Mejores prácticas

  • Mantén los controladores ligeros; mueve la lógica de dominio a los modelos o a objetos de servicio.
  • Carga las asociaciones de forma anticipada con includes y supervisa los logs para detectar consultas N+1.
  • Modifica la base de datos únicamente a través de migraciones y haz commit de las mismas junto con el código.
  • Utiliza strong parameters para cada escritura y valida en la capa del modelo.
  • Añade índices de base de datos en las columnas que utilices para filtrar y ordenar.
  • Delega las tareas lentas a jobs en segundo plano en lugar de ejecutarlas en el ciclo de la solicitud.
  • Escribe un test por cada bug que corrijas y mantén la suite de pruebas rápida.

Errores comunes

  • Renderizar una lista sin includes y desplegar un problema de N+1 a producción.
  • Colocar la lógica de negocio en los controladores hasta que las acciones tengan cientos de líneas.
  • Usar params[:post] directamente en lugar de strong parameters.
  • Editar db/schema.rb a mano en lugar de escribir una migración.
  • Olvidar las opciones de dependent: y dejar registros huérfanos.
  • Recurrir a un service object o a una gem antes de que el modelo lo justifique.
  • Ejecutar consultas pesadas en las vistas en lugar de cargar los datos en el controlador.

Próximos pasos

Rails enseña una forma de pensar robusta: recursos, convenciones y un lugar único para cada responsabilidad. Si te gusta el modelo “batteries-included”, Laravel aplica la misma filosofía en PHP, mientras que Django lo hace en Python. Debido a que el enrutamiento de Rails se basa en recursos, la guía de REST APIs explica los conceptos fundamentales. Y dado que la mayoría de las aplicaciones de Rails funcionan sobre una base de datos relacional, el siguiente paso ideal es profundizar tus conocimientos de PostgreSQL.

En la practica

Los cuatro archivos detrás de un recurso

Cambia entre la ruta, el controlador, el modelo y la migración para ver cómo Rails conecta un recurso.

config/routes.rb
Rails.application.routes.draw do
  resources :posts do
    resources :comments, only: %i[index create destroy]
    member do
      post :publish
    end
  end

  namespace :api do
    namespace :v1 do
      resources :posts, only: %i[index show create update destroy]
    end
  end

  root "posts#index"
end

Carga de asociaciones

Acceder a una asociación dentro de un bucle genera una consulta por fila. Cárgala anticipadamente (eager load) una vez y toda la página ejecutará solo dos consultas.

Preferir
posts = Post.includes(:author, :comments).recent
posts.each { |post| puts post.author.name }
Evitar
posts = Post.recent
posts.each { |post| puts post.author.name }
# one query per post: the classic N+1

Aceptación de entradas

Los strong parameters definen una lista blanca de lo que una solicitud puede establecer. Pasar el hash bruto permite que un cliente asigne cualquier columna, incluyendo flags de administrador.

Preferir
def post_params
  params.require(:post).permit(:title, :body, tag_ids: [])
end
Evitar
Post.new(params[:post])
# mass assignment: role and admin are fair game

Compromisos

¿Es Rails la opción predeterminada correcta?

Rails sacrifica algo de libertad a cambio de velocidad de entrega. Es un gran trato hasta que tu aplicación supera las convenciones.

Strengths

  • Entregas funcionalidades, no tuberías

    El enrutamiento, las migraciones, la validación, los mailers, los jobs y el almacenamiento en caché están incluidos y ya conectados, por lo que un equipo pequeño puede construir un producto grande.

  • Las convenciones son un lenguaje compartido

    Cualquier desarrollador de Rails puede abrir cualquier aplicación de Rails y saber dónde están las cosas. Eso hace que la contratación y el onboarding sean drásticamente más fáciles.

  • El ecosistema de gems es profundo

    Devise, Pundit, Sidekiq, RSpec y muchos otros resuelven los problemas que toda aplicación termina enfrentando.

Trade-offs

  • La magia oculta el framework

    La convención parece sencilla hasta que algo no es convencional. Depurar requiere entender el código fuente subyacente de Rails, no solo tu propio código.

  • El rendimiento requiere atención

    Una aplicación de Rails ingenua no es lenta, pero las consultas N+1, la falta de índices y las vistas pesadas se acumulan. El profiling es una habilidad obligatoria, no opcional.

  • El full stack es opinado

    Rails asume HTML, una base de datos relacional y su propia gestión de assets. Si tu arquitectura diverge, lucharás contra los valores predeterminados más de lo que los aprovecharás.

Preguntas frecuentes

Preguntas frecuentes

Keep learning

Related topics from the roadmap.

$ comienza a aprender

Listo para aprender Rails?

Nuestro tutorial interactivo te guia a traves de Rails paso a paso — con quizzes y codigo real que puedes ejecutar en el navegador.