Cómo ‘AASM’ cambiará tu forma de pensar las máquinas de estados

Nicolas Diaz Almassio
Unagi
Published in
4 min readJun 29, 2022

¿Alguna vez tuviste que manejar diferentes estados dentro del ciclo de vida de un objeto?

Illustration by Nina Markaryan from Ouch!

Manejar todo el flujo de estados de un objeto puede volverse muy complejo, sobre todo si en este, existen muchos estados y transiciones. Deberíamos definir no sólo los posibles estados y los métodos que harían las transiciones de un estado a otro, sino también las restricciones y errores que podrían producirse. Por suerte existe ‘AASM — Ruby state machines’, que resuelve todos estos temas y aún más.

Esta maravillosa gema, nos permite agregar máquinas de estados finitos a nuestros modelos Ruby, facilitándonos el pasaje entre estados, validar las transiciones, generar scopes asociados a estados, y muchas cosas más.

Para poder hacerlo solo debemos agregar a nuestro Gemfile:

y en nuestra consola correr:

¡Y listo! Ya podemos agregar máquinas de estado a cualquier clase de Ruby, sin importar su clase padre (si es que tiene alguna), es decir, no se limita a objetos ActiveRecord.

Veamos un ejemplo para ver el verdadero poder de esta gema. Supongamos que somos unos grandes aficionados de la lectura de libros, y tenemos una lista de libros que deseamos leer, además de una gran biblioteca, y nos cuesta saber qué libros ya hemos terminado, cuáles estamos leyendo y cuáles no hemos comenzado a leer.

Supongamos que los posibles estados de nuestros libros sean los siguientes:

Cuando deseamos comprar un libro lo creamos como “listado”, luego podemos comprarlo, lo que lo dejaría como “adquirido”. Cuando comenzamos con su lectura pasaría a estar “en proceso”, y cuando lo terminemos va a estar “terminado”. En cualquier momento podemos decidir vender el libro, lo que lo volvería a dejar como listado. Este proceso reflejado en una máquina AASM, quedaría así:

Con tener esto armado, ya podemos realizar, por ejemplo:

Si no queremos que se levante la excepción y preferimos algo más sencillo como ‘true’ o ‘false’, le podemos decir a AASM que no sea quejoso.

La gema también nos facilita callbacks, por si queremos que alguna acción se realice antes o después de algún evento, como por ejemplo:

De esta forma, cada vez que se pase de “in_process” a “finished” se va a ejecutar el método “notify_somebody”.

Las protectoras del flujo de estados

Otra gran herramienta que provee la gema, son las ‘Guardas’, de las cuales podemos hacer uso si deseamos que alguna transición se realice sólo si se cumple una cierta condición. En nuestro ejemplo, si nuestro modelo posee la página por la que vamos leyendo el libro, podemos requerir que esta sea igual a la última página del libro para poder terminar de leerlo.

Y así de fácil ya construimos la máquina de estados finitos para nuestra colección de libros, hasta con protecciones para transicionar a un cierto estado cuando se cumpla la condición requerida.

En Unagi siempre intentamos no instalar una gran cantidad de gemas, por lo que somos selectivos con las que decidimos agregar. En el caso de ‘AASM’, ha logrado resolver más de un dolor de cabeza al momento de trabajar con distintos estados, por lo que la seguimos eligiendo.

--

--