Algunos detalles que deberías saber sobre ActiveRecord – Rails


Agile Web Development wit RailsActive Record es un de los temas más amplios que dispone Rails, veamos algunos aspectos necesarios para poder estar cómodos. Podríamos decir que Active Record, es una solución al problema de acceder a los datos de una base de datos, en la que cada tabla de la base de datos es una clase, por lo que cada fila es asociada con objetos. Cuando se crea un objeto, se añade una fila a la tabla de la base de datos. Cuando se modifican los atributos del objeto, se actualiza la fila de la base de datos.

Los “callbacks” de ActiveRecord

La primera vez que me encontré con los Callbacks de ActiveRecord pensé en que son el complemento ideal (lo sigo pensando, pero con algún que otro matiz) y que te permiten hacer pequeños trozos de código, “hooks” para complementar el ciclo de vida de un objeto ActiveRecord. Pero también hay como contraposición, por ejemplo, si buscas o hablas con otros desarrolladores sobre “callbacks ActiveRecord”, podríamos llevarnos otra impresión totalmente distinta, incluso si los has usado en algún momento dentro de algún proyecto, puede que incluso hayas tenido la sensación de haber perdido el control de tu código. No quiero decantarme sobre “sí a los callback” o “no a los callback”, creo que deben ser utilizados a conciencia y de hecho he hablado con otros compañeros desarrolladores, sobre si los utilizan, tienen la misma sensación, hay que tener cuidado y con conciencia de uso, además personalmente pienso que los callbacks son como “la fuerza sin control no sirve de mucho”.

Las acciones se pueden llevar a cabo son “before”, “after”, o incluso “around” de los eventos de ActiveRecord, como “save“, “validate“, o “create“. Además, los callbacks son acumulativas, lo que puedes tener dos acciones que ocurren como before_update , y se ejecutarán en el orden en que se producen.

Entonces podríamos llegar a pensar ¿Por qué querríamos saltarnos el uso de los callbacks?, ¿Cuándo necesito callbacks? o mejor, ¿En qué circunstancias aplicaría los callbacks?. Se me ocurren que algunas situaciones en las que podríamos no utilizarlos, por ejemplo en el envío de notificaciones por correo electrónico, cuando un usuario se ha registrado, en la actualización de las tablas relacionadas, pero también deberías considerar que si nuestro “Callback” se mantiene en el área de la propia responsabilidad de nuestro objeto, en este caso yo, utilizaría un callback. Tenemos que pensar y/o tener presente que por lo general, un modelo ActiveRecord tiene una responsabilidad y es la de interacción con la base de datos. Cuando el modelo traspasa la frontera establecida, se vuelve algo más complicado el mantenimiento.

No es ninguna coincidencia que los callbacks que son “before_*” se utilizan generalmente para preparar a un objeto para ser guardado, como sería el caso de operaciones como una actualización de timestamps o cuando queremos incrementar los contadores en el objeto, un like, es estos casos son el tipo de cosas que hacemos con los tipo “before_*” para guardar el objeto. Considera que estos casos no estoy viendo la efectividad de utilizar Redis para nuestros contadores o likes, eso lo veremos en otro post. Por otra parte, los callback “after_*”, se utilizan principalmente en relación con el save del objeto o en la persistencia del objeto. Una vez que hemos guardado el objeto, la finalidad inicial que tenía dicho objeto se ha cumplido, por lo que en este tipo de casos, son los callbacks que llegan a estar fuera de su área de responsabilidad, es entonces cuando nos encontramos con problemas .

Llegado a este punto también nos podríamos preguntar ¿qué pasa con los Observer?, ¿podríamos tomarlos como sustitutos de los Callbacks? bueno, podríamos tomarlos como un camino alternativo o como una dirección correcta para trasladar responsabilidades, que no entran en el objeto propiamente dicho, pero pienso o creo que realizan la misma función que los callbacks y además es muy probable que se nos olvide que tenemos Observer cuando tengamos algún bug en nuestra aplicación. Considera que los Observer son asignados a su clase cuando cargamos nuestra aplicación Rails al inicio y cuando se cumpla una condición al igual que los callback se ejecutarán. Los Observer en la versión de Rails 4 ya no están disponibles.

Sigamos con nuestra lógica de aplicación. Si pensamos en uno de los principios de SOLID Design Principles y concretamente en “Single Responsibility Principle”, en la que nos dice que un objeto sólo debería tener una única responsabilidad, en ese caso deberíamos pensar en aplicar otra técnica, en vez de un callback, un patrón decorador “Pattern Decorator”. Por ejemplo, si pensamos que tenemos un modelo en el que tenemos un callback “after_create” que envía una invitación a un usuario:

Model: en este caso estamos dando responsabilidades que no debería tener nuestro modelo, la de enviar una invitación. Estamos incumpliendo el principio SOLID de SRP.

class Invite < ActiveRecord::Base

after_create :send_invite # this is a callback into my model

private

def send_invite
      Notifier.some_invite(invite).deliver
end

end

Si queremos cumplir el princio de “Single Responsibility Principle” debemos pensar en aplicar el “Pattern Decorator”, que nos quedaría el modelo y el controlador de la siguiente manera:

Model:

class Invite < ActiveRecord::Base

………………………………. more code

end

Patrón Decorator utilizando draper:

class InviteDecorator < ApplicationDecorator

decorates Invite

def create
      save

      send_invite
end

private

def send_invite
       Notifier.some_invite(invite).deliver
end

end

Controller:

class InviteController < ApplicationController

def create

@invite = InviteDecorator.new(Invite.new(params[:id]))

if @invite.create 
……………… more code…..

end

end

end

Algunos consejos que intento aplicar en mis proyectos, es utilizar los Callbacks cuando se ejecuten en el mismo ámbito en las que se activan, como serían los casos que sea la causa de un before_save antes de guardar nuestro objeto. Si nos encontramos algún caso en el que esto no debería ser así, en ese caso me llevo la lógica del objeto a un “Pattern Decorator”.

También, no se debería hacer callback cuando excede la responsabilidad dentro del modelo, si vemos que tenemos más de una responsabilidad dentro de nuestro modelo, en ese caso deberíamos pensar en desacoplar dichas responsabilidades. Además, piensa que la responsabilidad de un modelo ActiveRecord es para interactuar con la base de datos, nada más. Cuando estamos exigiendo a nuestros modelos para enviar correos electrónicos, notificaciones, o lo que sea , estamos dando más responsabilidad a nuestro modelo de la en un principio debería ser. A ver no es malo, pero considera que a medida que cambian los requisitos y ten por seguro que van a cambiar, vamos a darle más responsabilidad al modelo con el fin de cumplir con esas nuevas responsabilidades adicionales adquiridas. Si limitamos las responsabilidades, el mantenimiento será algo más llevadero, si nuestra aplicación crece en el tiempo.

¿Qué opinión tienes al respecto?

3 comentarios en “Algunos detalles que deberías saber sobre ActiveRecord – Rails

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s