# Fragment caching keeping stale product prices

**URL:** <https://www.ruby-forum.com/t/fragment-caching-keeping-stale-product-prices/139041>\
**Category:** Rails\
**Created:** [May 30, 2008, 11:44am UTC](https://www.ruby-forum.com/t/fragment-caching-keeping-stale-product-prices/139041 "2008-05-30T11:44:58Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![random52k](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/7bcc69/32.png) [@random52k](https://www.ruby-forum.com/u/random52k)\
**Post date:** [May 30, 2008, 11:44am UTC](https://www.ruby-forum.com/t/fragment-caching-keeping-stale-product-prices/139041/1 "2008-05-30T11:44:58Z")

</div>

I’ve got a list of products in my system and a master list of products  
available from my distributor. Every night I import a new  
distributor product file and update the prices for my list of products  
if any of them have changed.

The code to import the new distributor catalog file runs from a rake  
task in my crontab and all of my products/show pages are cached, as  
well as my index pages, so after updating all the prices, the system  
still displays the old cached price.

I need to be able to expire the cache fragments from one of the models  
that deals with downloading and importing the new distributor catalog  
file, but as far as I can tell, it’s not possible to execute the cache  
expiration methods from a model. Is there any way I can manually  
expire these caches? Or call my cache\_sweeper from the model? My  
ProductSweeper looks something like this:

def after\_save(product)  
expire\_fragment(product\_path(product))  
#expire some more stuff here…  
end

The other option is to not cache the product price, which will require  
me to go through all my code and end my cache blocks before the price  
is displayed, then start the cache block afterwards, but I’d have to  
use two separate cache names, like ‘product\_info\_top’ and  
‘product\_info\_bottom’, which starts to get messy and something I  
wanted to avoid. I can’t find any sort of “no\_cache” specifier to  
wrap around a value in a cached block… Would be very useful…

So I’m wondering if anyone has any advice or suggestions… Thanks in  
advance for your help!

---

<div class="post-metadata">

**Author:** ![random52k](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/7bcc69/32.png) [@random52k](https://www.ruby-forum.com/u/random52k)\
**Post date:** [May 30, 2008, 5:42pm UTC](https://www.ruby-forum.com/t/fragment-caching-keeping-stale-product-prices/139041/2 "2008-05-30T17:42:35Z")

</div>

> def after\_save(product)  
> expire\_fragment(product\_path(product))  
> #expire some more stuff here…  
> end

Are you sure the

expire\_fragment(product\_path(product))

is expiring the same location that the

cache(whatever) do

is writing to?

Been there, done that. ☹

---

<div class="post-metadata">

**Author:** ![random52k](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/7bcc69/32.png) [@random52k](https://www.ruby-forum.com/u/random52k)\
**Post date:** [May 30, 2008, 7:40pm UTC](https://www.ruby-forum.com/t/fragment-caching-keeping-stale-product-prices/139041/3 "2008-05-30T19:40:20Z")

</div>

I believe so… I’m using:

\<% cache(product\_path(@product)) do -%\>  
cached version of product info  
\<% end %\>

and in my sweeper:

expire\_fragment(product\_path(product))

they should both refer to the same location, no?

On Fri, May 30, 2008 at 11:42 AM, Ar Chron

---

<div class="post-metadata">

**Author:** ![random52k](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/7bcc69/32.png) [@random52k](https://www.ruby-forum.com/u/random52k)\
**Post date:** [May 30, 2008, 11:10pm UTC](https://www.ruby-forum.com/t/fragment-caching-keeping-stale-product-prices/139041/4 "2008-05-30T23:10:29Z")

</div>

The issue might be that the import isn’t going through the normal route  
that would cause the sweeper to be invoked (no pass through the  
controller?).

What if you scrap the cached fragment manually in your import when you  
know you’re writing a new price? (Don’t know how your import works, so  
this is just a wag…)

---

<div class="post-metadata">

**Author:** ![random52k](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/7bcc69/32.png) [@random52k](https://www.ruby-forum.com/u/random52k)\
**Post date:** [May 30, 2008, 11:35pm UTC](https://www.ruby-forum.com/t/fragment-caching-keeping-stale-product-prices/139041/5 "2008-05-30T23:35:33Z")

</div>

On Fri, May 30, 2008 at 5:10 PM, Ar Chron  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> The issue might be that the import isn’t going through the normal route  
> that would cause the sweeper to be invoked (no pass through the  
> controller?).
> 
> What if you scrap the cached fragment manually in your import when you  
> know you’re writing a new price? (Don’t know how your import works, so  
> this is just a wag…)

that’s the question. How do you expire a fragment cache manually  
without going through the controller? My import method is in a model  
which is called from a rake task. It loops through all the products  
who’s prices have changed and updates them. But I have no way of  
invalidating the cache. I’ve now changed my caches so I exclude the  
price from the cache, but it’s pretty ugly. I’d love to be able to  
manually expire the cache from my import model. I can expire a file  
based cache easily by using FileUtils.rm\_r, but I don’t know how to do  
this with the default memory based cache which is used on my  
production machine. Thanks
