Creación de Máquinas de Estados con AASM en Ruby on Rails

Clase 29 de 34Curso Intermedio de Ruby on Rails

Resumen

¿Qué es una máquina de estados y cómo se construye?

Construir una máquina de estados en el desarrollo de software puede ser un desafío, pero con las herramientas adecuadas, se vuelve una tarea ordenada y eficiente. La implementación de una máquina de estados permite modelar la lógica de un sistema según los estados posibles y las transiciones entre ellos. En este caso, utilizamos la gema AASM para crear una máquina de estados en el modelo Task.

¿Cómo se instala la gema AASM?

Primero, instala la gema AASM agregándola a tu archivo Gemfile:

gem 'aasm'

Luego, en la consola de comandos, ejecuta:

bundle install

Para utilizar las funcionalidades básicas de AASM, asegúrate de incluir el módulo en tu modelo:

include AASM

¿Cómo se definen los estados y transiciones?

Dentro del modelo Task, se debe definir los estados y eventos de transición. A continuación, te muestro un ejemplo básico de cómo se configura:

aasm do
  state :pending, initial: true
  state :inprocess
  state :finish

  event :start do
    transitions from: :pending, to: :inprocess
  end

  event :finish do
    transitions from: :inprocess, to: :finish
  end
end

Estos bloques de código establecen que una tarea puede estar en estado pending, luego en inprocess y, finalmente, en finish.

¿Cómo vinculamos los estados a un campo específico?

AASM por defecto utiliza su propio método para manejar estados, pero puedes indicarle que use un campo específico, en este caso, estatus:

aasm column: 'estatus' do
  # definición de estados y eventos
end

Esto asegura que los estados se almacenen en el campo 'estatus' de tu modelo Task.

Auditoría de transiciones en la máquina de estados

Agregar capacidades de auditoría te permite registrar cada cambio de estado. Esto es fundamental para rastrear el ciclo de vida de las tareas y entender cómo evolucionan.

¿Cómo se implementan los callbacks?

AASM ofrece callbacks útiles que puedes aprovechar. El método after_all_transitions permite ejecutar código después de cada transición:

after_all_transitions :audit_status_change

def audit_status_change
  # lógica de auditoría
end

Aquí, audit_status_change es un método que puedes definir para registrar cambios de estado.

¿Cómo se almacena la auditoría?

Para ello, debes crear un campo transitions en tu modelo Task, que sea un array:

field :transitions, type: Array, default: []

Cada vez que ocurra una transición, se registrará un nuevo objeto que almacene el estado anterior, el nuevo estado y el evento que provocó el cambio. Aquí tienes un ejemplo de cómo se podría implementar:

def audit_status_change
  set(:transitions, transitions.push({
    from: aasm.from_state,
    to: aasm.to_state,
    event: aasm.current_event,
    timestamp: Time.zone.now
  }))
end

¿Cómo se prueba el funcionamiento?

Para probar la funcionalidad de la máquina de estados y los registros de auditoría:

  1. Abre la consola de Rails con rails console o usando el alias r c.

  2. Crea una instancia de Task y verifica su estado inicial:

    task = Task.first
    puts task.status # debería mostrar 'pending'
    
  3. Cambia los estados invocando eventos:

    task.start!
    puts task.status # debería mostrar 'inprocess'
    task.finish!
    puts task.status # debería mostrar 'finish'
    
  4. Revisa las transiciones auditadas:

    puts task.transitions.inspect
    

Animamos a los estudiantes a explorar y experimentar creando máquinas de estados en sus proyectos, ya que brindan un control mejorado y estructurado sobre los flujos de trabajo. Con práctica, no solo mejorarás tus habilidades de modelado, sino que también podrás entender mejor la evolución de los proyectos en los que trabajas. ¡Adelante y sigue aprendiendo!