Search code examples
ruby-on-railscachingactive-model-serializers

What is the recommended approach for invalidating the cache on active_model_serializers 0.10.0?


I'm using caching at the serializer level, which mostly works exactly as I want it to (e.g. the model's updated_at changes and the associated serializer get's invalidated in the cache).

However, in some cases, I need to be able to manually target a specific serializer and have it invalidate it's cache. As an example, we're currently building a question and answer feature, the question serializer contains last_answer_at and answer_count. I want the question to be cached for as long as possible, as it rarely changes, however if a new answer is created or an existing answer is deleted, I want to be able to target the associate question and have it invalidate it's cache.

I've investigated this a bit, and found that you can get the cache key by using:

serializer = QuestionSerializer.new(self)
adapter = ActiveModelSerializers::Adapter.create(serializer)
cache_key = serializer.cache_key(adapter)

However, that doesn't include the attributes portion of the cache key.

What I'm hoping to achieve here, is that a parent object (in my example a question) would contain a method such as:

def clear_cache
  Rails.cache.clear(cache_key)
end

def cache_key
  serializer = QuestionSerializer.new(self)
  adapter = ActiveModelSerializers::Adapter.create(serializer)
  serializer.cache_key(adapter)
end

...and in my child object, call it when creating or deleting answers.

after_create :clear_parent_cache

def clear_parent_cache
  question.clear_cache
end

Is there a better way of doing this? Can you recommend a way of consistently getting the correct cache key?

Thanks, Dan

Note: This is also raised as an issue on the Github repo (https://github.com/rails-api/active_model_serializers/issues/1816), posting here to ensure it's visible to a broader audience.


Solution

  • I don't think this is a direct issue to AMS.

    There is a really nice RailsCast on this matter. Just quoting the essential:

    class Comment < ActiveRecord::Base
      belongs_to :article, :touch => true
    end
    

    Adding :touch => true to the belongs_to relationship means that when a comment is created, updated or destroyed the article it belongs to is touched.