arrow_back Volver
Inicio keyboard_arrow_right Artículos keyboard_arrow_right Artículo

Trabajo con Enums en Ruby on Rails

Eduardo Ismael Garcia

Full Stack Developer at Código Facilito.

av_timer 4 Min. de lectura

remove_red_eye 10041 visitas

calendar_today 17 Septiembre 2019

En esta ocasión aprenderemos a trabajar con el tipo de dato enum en Ruby on Rails. El tema de enum es sin duda un tema muy interesante y al cual le podemos sacar mucho provecho. 😎

Si aún no sabes que es un enum, no te preocupes, tenemos un post en donde te lo explicamos con detalle, te invito a que te des una vuelta por él. ?

Bien, sin más dilación ¿Qué les parece si comenzamos?

Enums

Para este post estaré trabajando con mi modelo ShoppingCart.

# == Schema Information
#
# Table name: shopping_carts
#
#  id         :integer          not null, primary key
#  amount     :float
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

class ShoppingCart < ApplicationRecord
end

El cual como podemos observar es un modelo bastante sencillo.

Ahora, imaginemos que tenemos la necesidad de almacenar el estado actual de un carrito de compras. En mi ejemplo, un carrito de compras puede poseer 4 estados:

  • Creado
  • Cancelado
  • Pagado
  • Completado

Con esto en mente y conociendo todos los posibles valores que pueden ser almacenados, con certeza nuestra mejor opción será implementar un enum.

Para ello lo primero que debemos hacer es generar un nuevo campo en nuestro modelo. Este campo tendrá por nombre status, haciendo referencia al estado del carrito. El campo será de tipo integer.

rails g migration add_status_to_shopping_carts status:integer
rake db:migrate

El siguiente paso será implementar el método enum. Este método recibe como argumento un hash, el cual nos permite establecer que campo, de nuestro modelo, queremos definir como un enum, además, por supuesto, de proporcionar el listado de las posibles opciones.

class ShoppingCart < ApplicationRecord
  enum status: [:created, :canceled, :payed, :completed]
end

Y listo! de esta forma es como podemos definir un campo como enum.

Algo importante a mencionar es que todas las opciones son enumeradas conforme a estas se encuentran dentro de la lista. La enumeración comienza en el índice 0, en mi caso:

  • created = 0,
  • canceled = 1
  • payed = 2
  • completed = 3

Tomando esto en cuenta podemos definir un valor por default para nuestro campo status.

 def change
    add_column :shopping_carts, :status, :integer, default: 0
  end

En este caso indicó que todos los carritos de compras que se creen comenzarán con el estatus created, claro, siempre y cuando no indique lo contrario. 🤠

Creación, Consulta y Actualización

En mi caso, como he colocado un valor por default en la migración, puedo crear un carrito de compras sin la necesidad de indicar un valor para el campo status.

shopping_cart = ShoppingCart.create amount:100.00

shopping_cart.status
 => "created" 

Si deseamos podemos establecer un valor para nuestro campo enum al momento de crear nuestro objeto. Para ello existen tres formas: mediante un símbolo, un string o un número entero, el cual hace referencia a la posición de la opción.

ShoppingCart.create amount:100.00, status: :completed
ShoppingCart.create amount:100.00, status: 'payed'
ShoppingCart.create amount:100.00, status: 1

Si queremos obtener registros a partir del campo enum, el método where resulta muy sencillo. Por ejemplo, obtengamos todos los carritos de compras con estatus created.

ShoppingCart.where(status: :created)

De igual forma podemos trabajar con un string o un número entero.

ShoppingCart.where(status: 'created')
ShoppingCart.where(status: 0)

Si queremos actualizar el valor del campo basta con asignar, mediante un string, una de las opciones dentro de la lista. ?

shopping_cart.status
 => "created" 

shopping_cart.status = 'payed'
 => "payed" 

shopping_cart.save

shopping_cart.status
 => "payed" 

o de igual forma podemos hacerlo mediante un símbolo.

shopping_cart.status = :created
=> :created 

shopping_cart.save

shopping_cart.status
 => "created" 

o inclusive mediante un número entero.

shopping_cart.status = 2
=> :payed 

shopping_cart.save

shopping_cart.status
 => "payed" 

Es importante mencionar que si colocamos algún valor que NO se encuentre dentro de la lista obtendremos un error.

Métodos

Al ejecutar el método enum, este creará un par de métodos nuevos sobre nuestro modelo. Esto nos permitirán trabajar con el campo enum de una forma mucho más sencilla. Veamos. ?

Obtengamos todos los carritos de compras con el estatus sea payed. Para ello podemos apoyarnos, nuevamente, del método where o podemos apoyarnos de un scope.

El método enum genera un nuevo scope por cada una de las opciones en la lista. En mi caso como mi lista posee cuatro opciones, se generán cuatro nuevos scopes. Estos scopes tienen el mismo nombre que las opciones, así que son muy fáciles utilizar.

ShoppingCart.payed
ShoppingCart.created

ShoppingCart.canceled

ShoppingCart.completed

Si deseamos conocer si el campo enum almacena un valor en específico, basta con realizar la pregunta (Un método por cada opción) ?

shopping_cart = ShoppingCart.payed.last

#El valor es payed?
shopping_cart.payed?
 => true 

#El valor es created?
shopping_cart.created?
=> false 

#El valor es completed?
shopping_cart.completed?
=> false 

La sintaxis es muy clara.

Si queremos actualizar el valor de nuestro campo a una opción en particular haremos uso de los métodos con terminación ! (Un método por cada opción)

shopping_cart.canceled!
 => true 

shopping_cart.status
 => "canceled" 

shopping_cart.completed!
 => true 

shopping_cart.status
=> "completed" 

El método enum genera: un scope, un método con signo de interrogación (?) y un método con signo de admiración (!) por cada una de las opciones dentro de la lista.

Conclusión

Los enums son una excelente opción en aquellos casos en los cuales conozcamos de antemano todos los posibles valores a almacenar. Como pudimos observar implementar enums con Ruby on Rails es extremadamente sencillo, además que el framewok mismo nos ofrece herramientas para agilizar y hacer más ameno el trabajo con ellos. 🤖