API Caching

While back there was article on thoughbot about fast json apis (Fast JSON APIs in Rails with Key-Based Caches and ActiveModel::Serializers)

Things have changed a bit since that and nowdays AMS don’t support caching (coming in the future…)

So question goes, how do you handle caching in your api controllers?

I recently accomplished this by adding caches myself into PORO serializers that implement some JBuilder. Here’s the parts of one of mine that are relevant:

class ElectricConsumptionGraphDataSerializer
  def as_json
    Rails.cache.fetch(cache_key) do
      Jbuilder.encode do |json|
        json.time_zone time_zone
        json.data measurements_as_hashes
      end
    end
  end

  private

  def cache_key
    {
       serializer: self.class.to_s,
       stat_record: stat_record.updated_at
    }
  end
end

If the stat record (which is the parent of the data related to the chart) has been updated, then Rails will generate new data when #fetch is called. The serializer’s cache key contains the class of the serializer’s class name because there are other serializers that rely on the stat record for their expiration, and I don’t want the different serializers to clobber each other in the cache.

If I were going to do this all over again, knowing that I have to cache these pieces, I think I’d it with Rabl and then use fragment caching in my Rabl templates, which makes it much easier to do nested, Russian-doll style caches where sub-components of the API response have their own caches. (You can probably do this in JBuilder as well, but I’ve soured a little bit on JBuilder’s API.) One of the nice things about Rabl is that you can lay out your API in a view template in a nice, clean way, so creating an API response isn’t much different than building an HTML view.