Ruby on Rails: expirar la caché desde un script ó como activar los Sweepers como Observers
No sé si es que soy yo el liante o es que me da por hacer las cosas raras.
El caso es que me he encontrado con otro dolor de cabeza haciendo algo, en principio, relativamente sencillo.
Se trata de insertar en la BD un modelo desde un script, que más adelante será un rake. Todo iba bien, no es complicado:
m = MiModelo.new( :nombre => 'el nombre' ) m.save
Pero, algo olÃa mal, pues los listados de este modelo tienen una vista, y esta vista está cacheada, y si insertaba el modelo desde el script la vista no cambiaba, osea: no estaba expirando la caché.
El problema estaba en que todos los engranajes de expiración de cachés estaban en los sweepers y éstos sólo se activan si el código pasa por el application.rb, padre de todos los controladores, concretamente con el método: cache_sweeper, y no encontraba manera de activar los sweeper sin pasar por un controlador.
Estuve dando unas buenas vueltas y preguntando a colegas, resulta que la caché en Rails está altamente integrada con el controlador. Y esto tiene su sentido pues no hay caché sin renderizado y no hay renderizado sin llamada a un controlador. Pero cuando hablamos de expirar cachés no veo tan claro que deba seguir estando integrado con el controlador, pues, como vemos en mi ejemplo del script, pueden existir muchos escenarios donde sea necesaria una expiración de caché sin necesidad de pasar por un controlador.
Googleando por ahà encontré un post que según creo entender también se queja un poco del exceso de integración entre la caché y los controladores.
La primero aproximación que parece ocurrÃrsenos es la de usar un observer en vez de un sweeper pero el sweeper tiene implÃcitamente un montón de métodos muy útiles para realizar la tarea de expiración de caché, como son los expire_* y los renderizadores de urls al estilo mi_modelo_url.
Además si empezaba a migrar todos los sweepers a observers empezaba a salirme del camino de como le gusta a Rails que se hagan las cosas.
Pero es que resulta que al parecer a Rails no le gusta que se expiren cachés desde un script y el workarround para conseguirlo no es del todo limpio pero se ha conseguido activar los sweepers desde un script para que se disparen al insertar un nuevo modelo en la BD.
El workarround es obra de Daniel Rodriguez Troitiño y aquà podéis revivir la lucha hasta conseguirlo.
Está funcionando para 2.0.1 y no sé si funciona en otras versiones.
require 'action_controller/test_process' ActiveRecord::Base.observers = [MiSweeper] ActiveRecord::Base.instantiate_observers MiSweeper.instance.controller = ActionController::Base.new tr = ActionController::TestRequest.new MiSweeper.instance.controller.request = tr MiSweeper.instance.controller.instance_eval( '@url = ActionController::UrlRewriter.new(tr, {})' ) m = MiModelo.new( :nombre => 'el nombre' ) m.save
Vemos que se activa el sweeper como un observer y luego se inicializa con todo lo necesario para que funcione.
Muchas gracias a Daniel que se lo ha tomado como reto personal ;).
Octubre 20th, 2014 at 2:04 am
If you want to get a great deal from this piece of writing then you have to apply these strategies to your won blog.
Julio 6th, 2017 at 7:16 am
I’ve been exploring for a little bit for any high quality articles
or weblog posts in this kind of area . Exploring in Yahoo I finally stumbled upon this web site.
Reading this information So i am satisfied to express that I have an incredibly just right uncanny feeling
I came upon exactly what I needed. I so much indisputably will make sure to do not forget this website and
give it a look regularly.