Cache sweepers en los callbacks de las asociaciones


#1

Hola.

Estaba intentando utilizar la cache de páginas de Rails en un proyecto
y me he encontrado un problema.

La idea es la siguiente: tengo dos modelos (Grupo y Proyecto)
relacionados mediante una asociación habtm. Existen páginas para ver
la lista de grupos, la lista de proyectos o un grupo o un proyecto
determinado. Con las listas de grupos o proyectos no hay problema,
pero cuando se muestra a un grupo o un proyecto se muestra a que
grupos pertenece o que proyectos están asociados a ese grupo.

Mi idea es que los “sweeper” eran la forma de extraer el código que
restaura la cache del controlador, utilizando los callbacks de los
objetos a los que observan. El problema está que añadir o eliminar un
elemento de una relación no parece disparar los callbacks usuales
(after_create/update/save, etcétera) y por lo tanto el sweeper no se
da cuenta de ello.

He estado mirando y las asociaciones tienen sus propios callbacks
(after_add/destroy), pero no son “observados” por el sweeper, y
ademásal definirse en el modelo no hay forma de llamar a expire_page (o yo
no la veo).

La solución que he podido encontrar es utilizar filtros after
despuésde las acciones del controlador que necesito vigilar por las
asociaciones, aunque me gustaría no tener el código de caching en dos
lugares diferentes.

¿Alguien ha tratado con esto? ¿Alguna
solución?
Muchas gracias.


#2

Hola Daniel,

la verdad es que yo también voy a tener que resolver una
situaciónsimilar en breve, aunque aún no me he puesto, sin embargo ya he mirado
alguna cosita.

Los callbacks after_add / destroy son propios de la asociación, no de
los callbacks “típicos” de ActiveRecord, por eso parece que los
observers no le hagan caso.

Sin embargo sí que lo puedes invocar en la definición de la
relación
has_and_belongs_to_many :projects, :after_add => :sweep_my_cache

Y ahí me he quedado, así que me uno a la petición popular de ayuda.


#3

On 3/13/07, Fernando B. removed_email_address@domain.invalid wrote:

has_and_belongs_to_many :projects, :after_add => :sweep_my_cache

Y ahí me he quedado, así que me uno a la petición popular de ayuda.


Fernando B.
blog > http://www.inwebwetrust.net

Sí, he intentado ese camino, y se llama al after_add, pero desde el
modelo no se puede invocar a expire_page (es parte de
ActionController), por lo que habría que eliminar la página a mano, o
reproducir el funcionamiento de expire_page (que tampoco es tan
complicado), o hacer un include del módulo Page (aunque creo que en
este caso sólo podría utilizar cadenas con rutas y no hashes
describiendo una ruta).

Muchas gracias de cualquier forma, a ver si alguien más se ha cruzado
con el problema y ha conseguido otra
solución.


#4

On 3/14/07, Fernando B. removed_email_address@domain.invalid wrote:

En mi caso he hecho un update_attribute de un campo dejándolo igual que estaba.

Espero que te sirva de algo.

Supongo que funcionará, y excepto porque es un pelín “hack” no es mala
solución.
Al final me decidí a tener separadas las cosas con sweepers por un
lado y after_filters por otro. Es un pelín feo tener separado en dos
lugares el código, pero bueno.

Muchas gracias de cualquier modo. No está mal conocer soluciones
alternativas.


#5

Hola Daniel,

creo que he llegado a una solución, aunque aviso que no es lo
máselegante del mundo, pero he estado mirando en foros, otras listas de
correo e incluso en el propio código de Rails y no he visto la forma
correcta de hacerlo.

La solución consiste en añadir un :after_add en la relación que llame
a un método de tu modelo y en dicho método modificas el modelo al que
tienes asociado tu sweeper para que éste se ejecute y caduque la
caché.
En mi caso he hecho un update_attribute de un campo dejándolo igual que
estaba.

Espero que te sirva de algo.