Máquina de estados en Ruby on Rails

Máquina de estados en Ruby on Rails

Una Máquina de Estado, también conocida como Máquina de Estado Final, es un modelo de cálculo matemático utilizado para diseñar algoritmos.

Dicha máquina considera el cambio entre estados con orden y lógica en cada uno. La implementación es sencilla y puede evitar dolores de cabeza en el futuro.

En esta oportunidad, compartiré un modelo matemático con el que controlarás los cambios entre estados al momento de usar enums en tus modelos.

¿De dónde partimos al necesitar implementar esto?

Cuando comienzas un proyecto en Ruby on Rails (RoR) y utilizas los enum en tus modelos para guardar algún valor, generalmente validamos qué deberíamos tener y no, según sea el estado. Un ejemplo: Para llegar a la universidad, debo pasar por una primaria, secundaria o preparatoria. Cada una es un estado donde voy subiendo de grado, aunque puedo regresar a un estado anterior. Asimismo, tiene una secuencia definida.

Entonces, lo que buscamos al implementarla es tener un diseño claro de cuáles transiciones son posibles o no, según sea el caso.

Regresando a las máquina de estado, existen dos tipos:

  • Determinista: La transición desde un estado puede tener como destino un estado único.
  • No determinista: La transición desde un estado puede tener múltiples destinos.

Con esto, buscamos analizar si el modelo que creamos realmente tiene un comportamiento según el estado y si éste siempre termina en el mismo lugar o puede tener otro estado final.

Una vez explicado esto, vamos a crear nuestra aplicación en RoR, utilizando una gema para facilitar el uso de la máquina de estados.

En este orden, implementaremos una gema llamada `aasm`. Agregaremos un modelo en este ejemplo para agregar una máquina de estados finitos, pero puedes usarla en módulos o trabajos si es necesario.

Primero, necesitamos crear una nueva aplicación. Escribimos en la terminal:

`rails new personal-app`

En nuestras aplicaciones Rails, solíamos generar solo un enum en el modelo y dejarlo configurado con un valor predeterminado o vacío.

Hay algunos requisitos en los cuales se necesita un estado inicial y una transición a otro estado con un orden definido. No se puede saltar un estado hacia adelante o, en su caso, volver al anterior.

Ejecutamos `rails g model job aasm_state:string` y después `rails db:migrate`.

Para facilitar la explicación, describiremos cada paso, pero antes puedes copiar este código.

Debe incluir el módulo AASM para usar los métodos de la gem `aasm`. En este caso, tenemos una columna llamada `aasm_state` que agregamos al modelo, por lo que añadiremos esta columna en la migración. Si deseas agregar el atributo después de crear el modelo, deberás incluir la migración.

Hay dos estados:

  • Sleeping.
  • Running.

Al mismo tiempo, tenemos dos eventos:

  • Run.
  • Sleep.

El valor predeterminado es Sleep (dormir). Es por ello que agregamos el `initial: true`

Tenemos el estado de `sleeping` como el valor por defecto después de guardar el modelo.

La idea detrás de lo anterior es analizar los requisitos para los modelos que tienen enums. Aquí hay unos ejemplos:

  • Cuando inicia un valor predeterminado y avanza, el proceso debe finalizar en algún momento para evitar volver al valor anterior o inicial.
  • En caso de tener una lógica de negocio relacionada con pagos, si realizo uno con tarjeta de crédito, el valor inicial está pendiente después de la transición a en proceso o revisión. Mientras tanto, no se puede volver a estar pendiente. Solo tienen dos opciones: aprobado o denegado.
  • Al igual que un triatlón, no puedes saltarte una fase cuando tienes etapas o fases en tu modelo.

En resumen

Necesitas una máquina de estado cuando tienes una ruta clara de las transiciones de tu modelo. Puedes definir cuándo el estado tiene o no un orden específico, así como la cantidad de cambios que podemos reunir en nuestro modelo.

Éste puede verificar si una transición está permitida o no. Tal vez no te importe si el proceso se repite muchas veces, pero te importará terminar ese ciclo en algún momento.

Por lo general, la falta de contexto te lleva a agregar un tipo de enum sin saber si necesitas comenzar en algún punto o si depende de otro factor o modelo relacionado. Por lo tanto, sería una buena práctica preguntarse si considera lo siguiente:

  • Tiene punto de partida de algún estado por defecto.
  • Transiciones permitidas o no según su estado actual.
  • Proceso sencillo (no se puede volver atrás).

Hicimos una aplicación RoR implementando una máquina de estado, un concepto fácil de aplicar a tus proyectos. Recuerda que esto puede servir mucho cuando tienes una idea clara del modelo, como también puedes validar cada escenario y limitar que el modelo pueda hacer transiciones no permitidas.

Esto facilitará comprender los escenarios posibles. Por lo tanto, tendrás un panorama más claro de cómo van a comportarse tu modelo y sus interacciones.

Esperamos que esta guía haya sido clara para ti. Ahora que conoces este concepto, puedes aplicarlo a tus proyectos.


⚠️
Las opiniones y comentarios emitidos en este artículo son propiedad única de su autor y no necesariamente representan el punto de vista de Revelo.

Revelo Content Network da la bienvenida a todas las razas, etnias, nacionalidades, credos, géneros, orientaciones, puntos de vista e ideologías, siempre y cuando promuevan la diversidad, la equidad, la inclusión y el crecimiento profesional de los profesionales en tecnología.