Creating Cache Keys for Rails Relations

For years I have been using the cache_key_for_*  method, as seen in Rails Guides and many other places. Here is an example.

It works. But even this venerable snippet couldn’t escape the refactoring razor.

.size vs .count

First change is using products.size  instead of products.count . A minor change, but if ActiveRecord has already executed the sql query, using the .size  method will prevent it from executing another query, as .count  may cause.

Sean Griffin has a quick say in this battle. TL;DR Rails users should always use .size .

DateTime Number

Second, the original used a long chain of trys and then converting the DateTime of updated_at to number format. You might be breaking the law… of Demeter that is.  That ‘number’ format looks like this: 20150410030422. It’s just the date and time.

Well, you can accomplish the same thing without chaining so many methods: use .to_i. Read about it at the docs. This one method uses the UTC time and gives you the number of seconds since the Unix Epoch. It looks like this: 1428635331.

Both has the same 1 second resolution, but the refactored version is shorter, which may save memcached memory if you have a lot of keys. I just think it’s cleaner, and avoids all the method chains.

Assembly

Finally, we just need to assemble it all in a string. By putting the size and time value into an array, we can use all those wonderful enumerable methods. You could just as easily use string interpolation and avoid the map and join.

Important Footnote

Rails has been using nanosecond resolution for their cache_key method for a while, assuming your backend supports factional second datetime values. My method only has 1 second resolution. If you require more granularity for your cache keys, by all means, use the original cache_keys_for_*  method and change the .to_s(:number) to .to_s(:nsec).

Posted in Rails. Tagged with .