Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changing cache key not working #2031

Open
chrismanderson opened this issue Jan 16, 2017 · 3 comments
Open

Changing cache key not working #2031

chrismanderson opened this issue Jan 16, 2017 · 3 comments

Comments

@chrismanderson
Copy link

Expected behavior vs actual behavior

Changing a serializer-level cache key with the key option does not change the cache key.

Steps to reproduce

With a basic controller

class ZonesController < ApplicationController
  def index
    render json: Zone.all
  end
end

and basic serializer

class ZoneSerializer < ActiveModel::Serializer
  cache key: 'area', expires_in: 3.hours

  attributes :type, :key

  def type
    'Feature'
  end

  def cache_key
    @cache_key # for debug
  end
end

I would expect the cache key to resemble something like:

area/24-20160217165512052884/attributes/63c314f796ba5ea3898d4a639a9448f4

When instead the key is:

zone/24-20160217165512052884/attributes/63c314f796ba5ea3898d4a639a9448f4

I've verified that the expected key is not present in the cache (memcache in my case). The incorrect key that is being set instead is present in the cache and does contain the cached value, so the cache itself is working.

Environment

ActiveModelSerializers Version (commit ref if not on tag): 0.10.4

Output of ruby -e "puts RUBY_DESCRIPTION": ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin16]

OS Type & Version: 10.12.2

Integrated application and version (e.g., Rails, Grape, etc): Rails 5.0.1, api mode

Backtrace

(e.g., provide any applicable backtraces from your application)

Additonal helpful information

Occurs with both memcache/dalli and Rail's memory_store.

development.rb cache section:

# Enable/disable caching. By default caching is disabled.
if Rails.root.join('tmp/caching-dev.txt').exist?
  config.action_controller.perform_caching = true

  config.cache_store = :mem_cache_store, "localhost"
  config.public_file_server.headers = {
    'Cache-Control' => 'public, max-age=172800'
  }
else
  config.action_controller.perform_caching = false

  config.cache_store = :null_store
end
@EarlyZhao
Copy link

EarlyZhao commented Mar 24, 2017

cache key: 'some key'
the key is not working.

I also met this problem, it cause me some problems,when i generate different format json data for the same model in method Index and Show, it will confuse the two formats, as the cache key set by me not working, the cache data of two json format was treated as one, store in redis. I can't get two json formats for one object.

I checked the sourse code of gem, the key set in the model ***Serializer was not used first.

This is the sourse code generating the key store in redis or other db.

the key like this: "interviews/20-20170324091427000000/attributes"

  def object_cache_key
    if object.respond_to?(:cache_key)
      object.cache_key
    elsif (serializer_cache_key = (serializer_class._cache_key || serializer_class._cache_options[:key]))
      object_time_safe = object.updated_at
      object_time_safe = object_time_safe.strftime('%Y%m%d%H%M%S%9N') if object_time_safe.respond_to?(:strftime)
      "#{serializer_cache_key}/#{object.id}-#{object_time_safe}"
    else
      fail UndefinedCacheKey, "#{object.class} must define #cache_key, or the 'key:' option must be passed into '#{serializer_class}.cache'"
    end
  end

It call the method cache_key(maybe this: http://apidock.com/rails/ActiveRecord/Base/cache_key) first.

@ledhed2222
Copy link

I thought I ran into this problem today too (hadn't seen the issue) but after a brief source dive it looks like this is just a bit of documentation confusion. cache_key comes from the model, so if you want to override it you need to override it there. If for some reason (I happened to have one but it's definitely a rare need) you want to override from the serializer itself, the method to override is object_cache_key. So assuming we have a model, controller, and serializer for Koala it looks like this:

class Koala
  def cache_key
    "#{super}/eucalyptus"
  end
end

class KoalaController
  def show
    render Koala.find(params[:id])
  end
end

class KoalaSerializer
  attributes :id, :food, :claws
  def object_cache_key
    "#{object.cache_key}/from_serializer"
  end
end

@lazyatom
Copy link

I've just hit this too, but I think it's more than documentation confusion. If you pass a key option to the cache method in a serializer, it's not used anywhere as far as I can tell.

It's certainly not used in cache_key, which is what is passed to the cache store. That method does call adapter_instance.cache_key, which you might imagine would use the private class attribute _cache_key at some point, but it does not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants