ActiveRecord es el sistema que usa Rails para conectar tu aplicación con una base de datos sin escribir SQL a mano.
¿Suena complicado? No lo es. Con ActiveRecord, guardar un producto, buscar un usuario o borrar un registro se hace con una sola línea de Ruby. En esta lección vas a aprender exactamente cómo funciona ese sistema.
¿Qué es un ORM y por qué te importa?
Imagina que tienes una tienda en línea como las que usa Liverpool. Cada producto tiene nombre, precio y categoría. Esos datos viven en una tabla de base de datos.
Normalmente tendrías que escribir SQL: SELECT * FROM productos WHERE id = 1. Con ActiveRecord escribes: Producto.find(1). El resultado es el mismo, pero el código es mucho más limpio.
Un ORM (Object-Relational Mapper) traduce objetos de Ruby a registros de base de datos y viceversa. ActiveRecord es el ORM que viene integrado en Rails.
Carlos y su catálogo de productos
Carlos trabaja en una startup de tecnología en Monterrey. Su equipo está construyendo una plataforma de distribución para FEMSA. Necesitan guardar información de productos en la base de datos.
Carlos crea un modelo con este comando en la terminal:
rails generate model Producto nombre:string precio:integer categoria:string
Ese comando hace dos cosas importantes. Primero, crea el archivo app/models/producto.rb. Segundo, genera una migración que define la estructura de la tabla.
Luego Carlos ejecuta:
rails db:migrate
Listo. La tabla productos existe en la base de datos. Carlos no escribió ni una línea de SQL.
Las migraciones: tu historial de cambios
Una migración es un archivo Ruby que describe cómo debe cambiar tu base de datos. Rails las guarda todas en la carpeta db/migrate.
Cada migración tiene una fecha y hora en el nombre, por ejemplo: 20240315120000_create_productos.rb. Eso garantiza que se ejecuten en el orden correcto.
Así se ve la migración que generó Rails para Carlos:
class CreateProductos < ActiveRecord::Migration[7.1]
def change
create_table :productos do |t|
t.string :nombre
t.integer :precio
t.string :categoria
t.timestamps
end
end
end
La línea t.timestamps agrega automáticamente dos columnas: created_at y updated_at. Rails las actualiza solo.
Crear, leer, actualizar y borrar (CRUD)
Estas cuatro operaciones son el corazón de cualquier aplicación. ActiveRecord las hace simples.
Crear un registro
producto = Producto.new
producto.nombre = "Refresco Coca-Cola 600ml"
producto.precio = 18
producto.categoria = "Bebidas"
producto.save
O en una sola línea:
Producto.create(nombre: "Refresco Coca-Cola 600ml", precio: 18, categoria: "Bebidas")
Leer registros
# Todos los productos
Producto.all
# Un producto por ID
Producto.find(1)
# El primer producto
Producto.first
# Buscar por condición
Producto.where(categoria: "Bebidas")
Actualizar un registro
producto = Producto.find(1)
producto.update(precio: 20)
Borrar un registro
producto = Producto.find(1)
producto.destroy
Así de directo. Sin SQL, sin configuración extra.
Sofía y las validaciones
Sofía es desarrolladora en una agencia digital en Ciudad de México. Su cliente es una empresa de alimentos que compite con Bimbo en el mercado de pan de caja.
El cliente le pidió que nadie pudiera guardar un producto sin nombre ni precio. Sofía agregó validaciones al modelo:
class Producto < ApplicationRecord
validates :nombre, presence: true
validates :precio, presence: true, numericality: { greater_than: 0 }
end
Ahora, si alguien intenta guardar un producto sin nombre, ActiveRecord lo rechaza. El objeto devuelve false en save y guarda los errores en producto.errors.full_messages.
Sofía lo probó en la consola de Rails:
rails console
p = Producto.new(nombre: "", precio: -5)
p.save
# => false
p.errors.full_messages
# => ["Nombre no puede estar en blanco", "Precio debe ser mayor que 0"]
Gracias a eso, la base de datos nunca recibe datos sucios. El cliente quedó muy satisfecho.
Asociaciones entre modelos
Rara vez un modelo vive solo. Casi siempre hay relaciones: un pedido tiene muchos productos, un usuario tiene muchas direcciones.
ActiveRecord maneja esas relaciones con palabras simples:
class Pedido < ApplicationRecord
belongs_to :usuario
has_many :productos
end
class Usuario < ApplicationRecord
has_many :pedidos
end
Con eso, puedes hacer cosas como:
usuario = Usuario.find(1)
usuario.pedidos
# Devuelve todos los pedidos de ese usuario
pedido = Pedido.find(5)
pedido.usuario
# Devuelve el usuario dueño de ese pedido
Rails sabe qué columnas buscar porque sigue convenciones de nombres. El modelo Pedido espera una columna usuario_id en la tabla pedidos.
Roberto y el reporte de ventas
Roberto trabaja para una empresa distribuidora en Guadalajara. Su jefe le pidió un reporte de todos los productos con precio mayor a $500 en la categoría "Electrónica".
Roberto escribió esto en su controlador:
@productos = Producto.where(categoria: "Electrónica").where("precio > ?", 500)
Ese código genera una consulta SQL automáticamente. Rails pone los valores de forma segura para evitar inyecciones SQL.
Roberto también necesitaba mostrar el precio con formato. Usó un helper en la vista:
<% @productos.each do |producto| %>
<p><%= producto.nombre %> — $<%= producto.precio.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse %></p>
<% end %>
El reporte salió limpio. El jefe de Roberto lo imprimió para la junta del lunes.
Errores comunes al usar ActiveRecord
Olvidar correr rails db:migrate. Si creas una migración y no la ejecutas, la tabla no existe. Rails te mostrará un error de columna desconocida.
Usar find cuando el registro puede no existir. Producto.find(999) lanza una excepción si el ID no existe. Usa Producto.find_by(id: 999) que devuelve nil en lugar de error.
No usar validaciones. Sin validaciones, cualquier dato entra a tu base de datos. Eso incluye nombres vacíos, precios negativos o correos mal escritos. Siempre valida.
Llamar .all sin límite en tablas grandes. Si tu tabla tiene 500,000 registros, Producto.all los carga todos en memoria. Usa .limit(50) o paginación.
Confundir delete con destroy. El método destroy activa los callbacks del modelo y borra registros asociados si está configurado. El método delete borra directo en la base de datos sin pasar por el modelo. Casi siempre debes usar destroy.
La consola de Rails: tu mejor herramienta de prueba
Antes de escribir código en un controlador, prueba tus consultas en la consola:
rails console
Desde ahí puedes crear, buscar y borrar registros en tiempo real. Es como tener una calculadora para tu base de datos.
Si quieres probar sin guardar cambios reales, usa:
rails console --sandbox
Todo lo que hagas en modo sandbox se revierte al salir. Muy útil para explorar sin miedo.
Lo que aprendiste hoy
ActiveRecord convierte tu base de datos en objetos Ruby. Creas migraciones para definir tablas, usas el modelo para guardar y consultar datos, y las validaciones protegen la calidad de tu información.
Con estos fundamentos, ya puedes construir la capa de datos de cualquier aplicación web. En la próxima lección vas a conectar todo esto con vistas y controladores para mostrar datos reales en el navegador.