Revista Informática

Ruby on Rails desde Cero: Serializar Objetos (active_model_serializers)

Publicado el 18 octubre 2013 por Codehero @codeheroblog

¿Qué hace la gema active_model_serializers?

Esta gema básicamente nos ayuda a serializar los objetos, al igual que como hicimos en el capítulo anterior usando ActiveModel::Serializers, pero con la diferencia que esta gema nos agrega una serie de funcionalidades que nos ayudan al manejo de estos objetos e incluso nos separan la lógica de serialización de nuestros controladores y modelos. Por lo general utilizamos esta gema para realizar APIs con formato JSON.


Demostración

Para la demostración de esta maravillosa gema veremos desde su instalación hasta la implementación, en algunos ejemplos sencillos, que podrás desarrollar fácilmente tu aplicación.

Instalación

Hasta este momento no hemos visto ni instalado ninguna gema en nuestra aplicación, ya es hora de hacerlo y como todo en Ruby on Rails te daras cuenta de lo fácil que resulta.

Básicamente la instalación de esta gema, en Ruby on Rails y en nuestra aplicación, sigue dos sencillos pasos. Primero agregamos en el archivo Gemlife nuestra gema de la siguiente manera:

gem "active_model_serializers"

1 gem"active_model_serializers"

Luego, nos vamos a nuestra consola o terminal y nos dirigimos hasta el directorio donde está el proyecto. Entramos dentro de la carpeta del proyecto y ejecutamos la famosa línea de código para instalar las gemas:

bundle install

1 bundle install

Una vez realizados estos dos sencillos pasos ya nuestra aplicación está lista para hacer uso de nuestra gema serializadora.

¿Cómo creamos el serializador?

Para crear el serializador sólo basta con ejecutar un línea de comando en nuestra consola o terminal. Si queremos crear un modelo desde cero y ya estamos seguros que vamos a necesitar serializar los objetos, porque queremos hacer un API o simplemente queremos mostrarlo en un formato de uso común (JSON), utilizamos el siguiente comando:

rails g resource nombre_modelo atributo1:string atributo2:string

1 railsgresource nombre_modelo atributo1:stringatributo2:string

o

rails generate resource nombre_modelo atributo1:string atributo2:string

1 rails generate resource nombre_modelo atributo1:stringatributo2:string

Como ven este comando nos crea los mismos archivos que cuando creamos un modelo, sólo que adicionalmente en la carpeta app nos agrega una nueva carpeta llamada serializers y a ésta un archivo Ruby donde desarrollamos la lógica para serializar.

También es posible crear un serializador a un objeto ya existente en nuestra aplicación de la siguiente manera:

rails g serializer nombre_modelo

1 railsgserializer nombre_modelo

o

rails generate serializer nombre_modelo

1 rails generate serializer nombre_modelo

Este comando sólo nos crea la clase en Ruby, donde desarrollamos la lógica para serializar el objeto que indicamos.

¿Cómo usar el serializador?

Una vez que creamos nuestro serializador nos damos cuenta que tenemos unos archivos Ruby nuevos dentro de la carpeta Serializer que se debió haber creado. Estos archivos deben tener algo como esto:

class UsuariosSerializer < ActiveModel::Serializer attributes :id, :nombre, :apellido, :nacimiento, :sexo end

123 classUsuariosSerializer&lt;ActiveModel::Serializer  attributes:id,:nombre,:apellido,:nacimiento,:sexoend

Como ven es una simple clase que extiende de ActiveModel::Serializer con los atributos del modelo que en nuestro caso es Usuario.

Probablemente cuando creamos el serializador con la segunda opción de este tutorial, debamos agregar los atributos del modelo a mano (Por defecto sólo se crea con el id)

Una vez revisada y modificada la clase serializadora del modelo simplemente nos vamos a nuestro controlador y creamos un método (Recuerda agregar la ruta al archivo routes.rb). Por ejemplo:

class Usuario < ApplicationController def serializador @ejemplo1 = Usuario.all render json: @ejemplo1 end end

12345678 classUsuario&lt;ApplicationController   def serializador  @ejemplo1  =Usuarioall  render json:@ejemplo1  end end

Listo!, con este comando ya tenemos a todos los usuarios impresos en formato JSON en nuestra aplicación.

{ "nombreControlador": [ { "id": 6, "nombre": "Ramses", "apellido": "Velasquez", "nacimiento": "1968-05-09", "sexo": "m" }, { "id": 7, "nombre": "Perez", "apellido": "Juana", "nacimiento": "1996-05-09", "sexo": "f" } ] }

123456789101112131415161718 {  "nombreControlador":[  {  "id":6,  "nombre":"Ramses",  "apellido":"Velasquez",  "nacimiento":"1968-05-09",  "sexo":"m"  },  {  "id":7,  "nombre":"Perez",  "apellido":"Juana",  "nacimiento":"1996-05-09",  "sexo":"f"  }  ]}

¿Cómo cambiar la estructura del JSON?

Probablemente necesitemos ocultar algunos atributos de nuestro modelo, cambiar el formato del algunos atributos e incluso agregar funciones que puedan cambiar la estructura de nuestro modelo original. El uso de funciones, el manejar la lógica de serialización completamente separada de nuestra aplicación y poder definir nuestros propios atributos, es lo que hace verdaderamente útil esta gema.

Imaginemos que necesitamos a los usuarios, pero en este caso particular sólo nos hace falta el nombre completo y la fecha de nacimiento de cada uno de los usuarios. Debemos desarrollar el serializador de la siguiente forma:

class UsuarioSerializer < ActiveModel::Serializer attributes :nacimiento, {full_name: :full_name} def full_name "#{object.nombre} #{object.apellido}" end end

1234567 classUsuarioSerializer&lt;ActiveModel::Serializer  attributes:nacimiento,{full_name::full_name}   def full_name  "#{object.nombre} #{object.apellido}"  endend

Como ven en el ejemplo, desarrollamos una función llamada full_name donde concatenamos el nombre, ya que, para nuestro uso interno usamos el nombre por separado. Por último, para mostrar los atributos que queremos simplemente los sacamos o agregamos a nuestra lista de atributos.

Si deseáramos agregarle información extra a nuestra salida en formato JSON pudiéramos agregarlo directamente en nuestro controlador con la etiqueta meta. Veamos el siguiente ejemplo y la salida que genera:

def serializador @ejemplo1 = Usuario.all # meta_key es para cambiarle el nombre a la etiqueta que estamos agregando render json: @ejemplo1 , meta: {total: 10}, meta_key: 'meta_object' end

12345 def serializador  @ejemplo1  =Usuarioall  # meta_key es para cambiarle el nombre a la etiqueta que estamos agregando  render json:@ejemplo1,meta:{total:10},meta_key:'meta_object'  end

Para tener una salida parecida a la siguiente:

{ "nombre_controlador": [ { "nacimiento": "1988-05-09", "full_name": "Ricardo Sampayo" } ], "meta_object": { "total": 10 } }

1234567891011 {  "nombre_controlador":[  {  "nacimiento":"1988-05-09",  "full_name":"Ricardo Sampayo"  }  ],  "meta_object":{  "total":10  }}

Por último, para terminar con este punto, esta gema también nos ofrece la posibilidad de tener varios serializadores con estructuras diferentes para ser usados según sea el caso. Por ejemplo, el serializador que hemos utilizado hasta ahora sólo tiene fecha de nacimiento y el nombre completo, pero, pudiéramos necesitar otro serializador que provea toda la información del modelo sin necesidad de aplicarle cambios al serializador principal. Veamos en el siguiente ejemplo cómo podemos llamar a un serializador diferente.

def serializador @ejemplo1 = Usuario.first render json: @ejemplo1 , serializer: UsuarioCustomSerializer end

1234 def serializador  @ejemplo1  =Usuariofirst  render json:@ejemplo1,serializer:UsuarioCustomSerializer  end

En caso de que el objeto que vayamos a serializar sea un arreglo de objetos utilizamos el siguiente:

def serializador @ejemplo1 = Usuario.all render json: @ejemplo1 , each_serializer: UsuarioCustomSerializer end

1234 def serializador  @ejemplo1  =Usuarioall  render json:@ejemplo1,each_serializer:UsuarioCustomSerializer  end


Conclusión

En esta lección hemos estudiado una nueva y muy útil gema para desarrollar en Ruby on Rails. Esta gema, aunque ofrece algunas funciones que ya nos ofrece el framework y estudiamos en el capítulo anterior ActiveModel, nos otorga más libertad al serializar nuestros objetos y aún más importante nos mantiene el código separado de la lógica de negocios manteniendo el código limpio, ordenado y eficiente.

Una vez más te recomiendo echarle un vistazo a la serie completa de Ruby desde cero, así como a las otras series de CodeHero, agradeciendo de antemano todas sus dudas y comentarios en la sección de comentarios.

¡Hasta el próximo capítulo!


Volver a la Portada de Logo Paperblog