Callbacks en Controladores y Modelos en Rails

Clase 29 de 36Curso de Introducción a Ruby on Rails

Contenido del curso

Nuestra primera aplicación

Resumen

Dominar el concepto de callback en Ruby on Rails es fundamental para controlar lo que ocurre antes o después de eventos clave en controladores y modelos. Comprender cómo intervenir en el ciclo de vida de una petición o de la persistencia de un registro permite automatizar procesos, garantizar integridad de datos y escribir código más limpio y predecible.

¿Qué son los callbacks en controladores y cómo funcionan?

Un callback es un método que se ejecuta automáticamente en un momento específico del ciclo de vida de un recurso. En el caso de los controladores, ya se habían utilizado dos ejemplos claros dentro del archivo ApplicationController [0:20]:

  • before_action :set_locale — ejecuta la lógica de internacionalización antes de cualquier acción.
  • before_action :authenticate_user — verifica la autenticación del usuario antes de procesar la petición.

La idea central es sencilla: cuando una petición llega al servidor, pasa por el enrutamiento y luego llega a la acción de un controlador. Con before_action, le indicamos que antes de ejecutar esa acción, debe ejecutar otra cosa primero [0:42]. También existe after_action, que permite ejecutar lógica después de que la acción se haya completado.

¿Cómo se traslada este concepto a los modelos?

Algo similar ocurre con los modelos de Active Record. En lugar de interceptar acciones HTTP, los callbacks de modelos interceptan eventos del ciclo de vida de persistencia: creación, actualización y destrucción de registros [1:20].

Para experimentar con esto, se propone un ejercicio práctico: generar automáticamente un código único antes de crear cualquier tarea.

¿Cómo crear un callback before_create en el modelo Task?

El primer paso es agregar una columna code de tipo string a la tabla tasks. Para ello se genera una migración desde la consola [1:48]:

bash rails generate migration AddCodeToTask code:string rails db:migrate

Esto crea la columna code en la tabla tasks y la hace disponible como atributo del modelo.

Dentro del modelo Task, se declara el callback before_create apuntando a un método personalizado [2:40]:

ruby class Task < ApplicationRecord before_create :create_code

private

def create_code self.code = "#{owner_id}-#{Time.now.to_i.to_s(36)}-#{SecureRandom.hex(8)}" end end

¿Qué hace exactamente el método create_code?

El método construye un código único combinando tres elementos [3:05]:

  • owner_id — identifica al propietario de la tarea.
  • Time.now.to_i.to_s(36) — convierte la estampa de tiempo actual a un entero y luego lo representa en base 36 para reducir la cantidad de caracteres.
  • SecureRandom.hex(8) — genera un hexadecimal aleatorio de 8 bytes que garantiza la unicidad incluso si dos tareas se crean en el mismo instante.

El uso de self.code es clave: indica que estamos asignando el valor al atributo code de la instancia actual del modelo, justo antes de que el registro sea persistido en la base de datos [3:55].

¿Cómo verificar que el callback funciona correctamente?

Después de crear una tarea desde la interfaz gráfica, se puede comprobar el resultado desde la consola de Rails [4:20]:

bash rails console Task.last

El último registro mostrará un campo code con la estructura esperada: el ID del usuario (por ejemplo, el usuario número 2), la representación de la estampa de tiempo y el hexadecimal generado por SecureRandom [4:40].

¿Dónde encontrar todos los callbacks disponibles en Active Record?

Rails ofrece una amplia variedad de callbacks que cubren distintos momentos del ciclo de vida de un objeto. La referencia completa se encuentra en las Rails Guides, específicamente en la sección Active Record Callbacks, apartado Available Callbacks [5:20].

Allí se listan los métodos disponibles organizados por tipo de operación:

  • Creación: before_validation, after_validation, before_save, before_create, after_create, after_save.
  • Actualización: misma estructura con before_update y after_update.
  • Destrucción: before_destroy y after_destroy.

Cada uno permite ejecutar lógica personalizada en el momento preciso, ya sea para generar códigos automáticos, validar condiciones adicionales o limpiar datos relacionados.

Si quieres profundizar en otros callbacks o compartir cómo los utilizas en tus proyectos, deja tu experiencia en los comentarios.