Caching an Object in Rails is Easy

23 Sep 2012

Caching in Rails is really simple (straight from the docs):

_You can set up your application’s default cache store by calling config.cache_store= in the Application definition inside your config/application.rb file or in an Application.configure block in an environment specific configuration file (i.e. config/environments/*.rb). The first argument will be the cache store to use and the rest of the argument will be passed as arguments to the cache store constructor.
_

Originally, I didn’t even know it was there. So I was thinking I’d just create a hash in memory. So I wrote my own cache class like this (homegrown_cache.rb):

# not exactly a pure cache, implements the lookup or expensive operation too# probably needs to be decoupled</p>classCachedefinitialize@cache={}enddefcache(name,values={})ifvalues={}return@cache[name.to_sym]else@cache[name.to_sym]||=valuesendenddefsearch(name)if@cache.keys.include?(name.to_sym)puts"getting name from cache instead of expensive operation"return@cache[name.to_sym]elseself.cache(name,Expensive::Search(name))return@cache[name.to_sym]endenddefclearcache_size=@cache.length@cache={}returncache_sizeenddefto_s"#<Cache:#{self.object_id} Cache Size: #{@cache.length}>"enddefsize@cache.lengthendend

Then you might want to use it in an implementation like like CacheEnabledSearch or something like that within your app.
But it's way easier and smarter to just use the goddamn caching that's built into Rails. Specifically, if you use the in memory store, since Rails 3.0 **it's thread safe**. Meaning if two clients hit your cache, you're not going to have weird bugs pop up. It's very easy to configure and use.
I'm posting the Cache class anyway though it's interesting how simple an object it is without being thread-safe. But even then, I'd recommend using the cache class from Rails outside of Rails.
So here's how you'd use Rails caching "without" Rails. In other words, a console app.

Not particularly interesting. This would be way more useful inside of a Rails app where a singleton class called Rails.cache is set [if you have something set in your config](http://guides.rubyonrails.org/caching_with_rails.html#activesupport-cache-memorystore):
`config.cache_store = :memory_store`
Let's avoid the Rails situation for now and create a file cache directory for a file based cache:
`$ mkdir /tmp/poro_cache`
Here's a complete example.

If we run this one time, we get this:
`ruby rails_cache_poro.rb
wrote to cache, run me again`
And running it again:
`ruby rails_cache_poro.rb
Reading from filestore cache: bob`
Reset it with `rm -rf /tmp/poro_cache`
Ok, so that's ActiveSupport caching outside of Rails. Wiring Rails up to do this inside a controller, lib class, helper or other ruby object is trivial once you have followed the [caching guide](http://guides.rubyonrails.org/caching_with_rails.html#activesupport-cache-memorystore). You won't instantiate ActiveSupport::Cache anymore directly but you'll do it indirectly through the config block for your environment.
And then all the statements will look like this:

>>Rails.cache.write'foo','bar'=>true

But it works the same. Really easy. Of course, the next subject which is more complicated is [when to invalidate your cache](http://jeffdickey.info/cache-correctly-stop-invalidating).