Simple expiring caching for Ruby on Rails

Ruby on Rails has some great caching support built right in, but it’s most useful when you have MemCacheD or DRb around to serve as a cache store. I don’t have access to those everywhere - Dreamhost and other shared hosting providers often prohibit running your own MemCacheD. There’s a default memory store, but it won’t share cached info between Rails server processes. That leaves the file store, which just writes cached objects to a file that gets shared between all your Rails processes on the same box. The main problem with the file store is that it doesn’t support time-based expiration - you have to set up a cron job to sweep out the cache files every once in a while to invalidate your cache.

To get around this, I wrote a tiny, obvious little module that gives a simple syntax for caching objects with the file store. The trick is that it stores the insert time whenever it caches a new object, and compares it with the current time every time it looks it up. If the cached object is too old (or the cache is empty), it throws it away and executes the provided block and caches the new value.

Be sure to use the same expiration whenever you fetch the same object, or things will expire differently depending on where they’re accessed. You can also do a bit of customization for more complex cache invalidations - I have a version of fetch that caches objects within one calendar day and recalculates them only when the date is different. I suppose I could made fetch take an optional Proc to control the caching strategy, but I didn’t really need that much customization. Anyway, this isn’t exactly brilliant new code, but it has made caching objects from my smaller Rails apps a bit easier.

Update: It looks like Rails 3 just supports :expires_in natively for FileStore.

I'm Benjamin Hollis, a software developer in Seattle. Check out my website.