La razón es porque
User.where('status = 1').limit(1000)
devuelve un ActiveRecord::Relation
que en realidad es tan hacer frente, no una consulta. Rails almacena en caché el alcance.
Si desea almacenar en caché la consulta, debe utilizar un método de consulta al final, como #all
.
Rails.cache.fetch(key) do
User.where('status = 1').limit(1000).all
end
Tenga en cuenta que nunca es una buena idea para almacenar en caché los objetos ActiveRecord. El almacenamiento en caché de un objeto puede provocar estados y valores incoherentes. Siempre debe almacenar en caché objetos primitivos, cuando corresponda. En este caso, considere almacenar en caché los ids.
ids = Rails.cache.fetch(key) do
User.where('status = 1').limit(1000).pluck(:id)
end
User.find(ids)
Se puede argumentar que en este caso, una llamada a User.find
que siempre ha ejecutado. Es cierto, pero la consulta que utiliza la clave principal es rápida y soluciona el problema que describí anteriormente.Además, el almacenamiento en caché de objetos de registro activos puede ser costoso y puede terminar llenando rápidamente toda la memoria de Memcached con solo una entrada de caché. Los ID de almacenamiento en caché también evitarán este problema.
thx. Si tengo un modelo de categoría, puede tener menos de 100 registros, guardo en caché la Categoría. ¿Es una buena idea? no almacenar en caché la identificación de cateogria – tinylian
¿O primero cambio Category.all a json y los guardo en caché en memcached? – tinylian
Este es un problema muy importante y sutil; nos dimos cuenta de que este problema se había infiltrado en nuestra aplicación: la diferencia entre 'Foo.where (bar: 'fubar')' y 'Foo.where (bar: 'fubar'). all' es completamente diferente w/r/t caché, y algo que puede deslizarse fácil y sutilmente en su código base. Verifique y verifique regularmente si confía en el almacenamiento en caché. –