Caching ActiveRecord Objects with Rails.cache file_store
Rails 2.1 presents Rails.cache, a clean little interface for caching stuff. It makes it easy to switch between different cache stores. For example, we are using memcached in production but something else, like the file system, in development where performance and scalability aren’t as important as forward progress.
Memcached supports the caching of ActiveRecord objects, so you can do something simple like this:
all_things = Rails.cache.fetch('Thing.all') { Thing.all }
This single line of code looks for a cache entry by the key “Thing.all”. If it’s not found, the code in the block is executed and the results are added to the cache and returned. If that cache entry is found, the value is returned from the cache, avoiding a trip to the database. Very useful for things that rarely change.
This works great with memcached store, but not with file store, which seems to prefer simple strings. A workaround is to convert the ActiveRecord objects to YAML when putting them in the cache and converting back from YAML when reading:
all_things = YAML::load(Rails.cache.fetch('Thing.all') { Thing.all.to_yaml })
I recommend encapsulating this in a class method:
class Thing < ActiveRecord::Base
def self.all_cached
YAML::load(Rails.cache.fetch('Thing.all') { all.to_yaml })
end
end
So in order to use Rails.cache in the context of persistent file storage mechanism, one must serialize the contents? I think that your suggestion around encapsulation was a very good one. However, it belongs in the cache itself. The underlying storage of objects in the cache shouldn’t impose type requirements on the consumer… especially in such a loosely typed paradigm.
Hey Matt,
To be fair, I’m not surprised that you have to serialize the data you want to cache in the file store (file systems don’t store “objects” after all, so some marshaling must happen somewhere), although it would be nice if Rails were smart enough to do it automatically… which it *should* be able to do, and I suspect could be patched easily enough if one were so inclined, putting the serialization code in the file store caching strategy where it belongs (not in the model).
That’s something I did consider but haven’t reached the threshold of pain yet, since we’re only using this strategy in a few models.
this is like a bug in rails that needs to be stomped out