Search code examples
cachingactive-model-serializersrails-api

How to use a dynamic value for cache key with ActiveModel::Serializers (v0.10.0.rc1)


I am using a database-driven solution for labels and translations that I would like to cache at the serializer level. Here is my serializer.

class AppLabelSerializer < ActiveModel::Serializer
  cache key: 'app_label', expires_in: 3.hours
  attributes :id, :key, :label, :label_plural

  def key
    object.app_label_dictionary.key
  end
end

The problem is that I need to cache the labels for each language, so I need to specify the language somewhere in the key. I tried this solution:

cache key: "#{scope.app_language.name}/app_label", expires_in: 3.hours

But the value of scope isn't available there for some reason.


Solution

  • I posted an issue on the AMS github page and went back and forth with @joaomdmoura and @groyoh until we came up with this temporary solution. It works on my end and it'll do for now until AMS makes an official decision on the best solution.

    module ActiveModel
      class Serializer
        class Adapter
          def cache_key
            key = @klass._cache_key
            key = @cached_serializer.instance_exec &key if key.is_a?(Proc)
            key ? "#{key}/#{@cached_serializer.object.id}-#{@cached_serializer.object.updated_at}" : @cached_serializer.object.cache_key
          end
        end
      end
    end
    
    class AppLabelSerializer < ActiveModel::Serializer
      cache key: ->(){ "#{scope.app_language.name}/app_labels" }, expires_in: 3.hours
      attributes :id, :label, :label_plural    
    end
    

    It looks funny, but yes you just paste in that extension of the ActiveModel module right into your already existing serializer file.

    NOTE: This only works with v0.10.0.rc1