class ActiveModelSerializers::FragmentCache

def add_attributes_to_serializer(serializer, attributes, attributes_keys)

def add_attributes_to_serializer(serializer, attributes, attributes_keys)
  attributes.each do |attribute|
    options = attributes_keys[attribute] || {}
    serializer.attribute(attribute, options)
  end
end

def cache_attributes(serializers)

3. Add non-cached attributes to non-cached Serializer
2. Add cached attributes to cached Serializer
1. Determine cached attributes from serializer class options
Given a hash of its cached and non-cached serializers
def cache_attributes(serializers)
  klass                 = serializer.class
  attributes            = klass._attributes
  cache_only            = klass._cache_only
  cached_attributes     = cache_only ? cache_only : attributes - klass._cache_except
  non_cached_attributes = attributes - cached_attributes
  attributes_keys       = klass._attributes_keys
  add_attributes_to_serializer(serializers[:cached], cached_attributes, attributes_keys)
  add_attributes_to_serializer(serializers[:non_cached], non_cached_attributes, attributes_keys)
end

def fetch

3. Pass their serializations to the adapter +::fragment_cache+
2. Serialize the above two with the given adapter
1. Create a CachedSerializer and NonCachedSerializer from the serializer class
def fetch
  object = serializer.object
  # It will split the serializer into two, one that will be cached and one that will not
  serializers = fragment_serializer
  # Get serializable hash from both
  cached_hash     = serialize(object, serializers[:cached])
  non_cached_hash = serialize(object, serializers[:non_cached])
  # Merge both results
  adapter.fragment_cache(cached_hash, non_cached_hash)
end

def fragment_serializer


NonCachedUser_AdminSerializer
CachedUser_AdminSerializer
creates the Serializer classes (if they don't exist).
When +name+ is User::Admin
@example

5. Return the hash
4. Call +cached_attributes+ on the serializer class and the above hash
3. Build a hash keyed to the +cached+ and +non_cached+ serializers
NonCachedSerializer.cache(serializer._cache_options)
CachedSerializer.fragmented(serializer)
CachedSerializer.cache(serializer._cache_options)
2. Call
for a given class 'name'
1. Dynamically creates a CachedSerializer and NonCachedSerializer
Given a resource name
def fragment_serializer
  klass                 = serializer.class
  serializer_class_name = to_valid_const_name(klass.name)
  cached     = "Cached#{serializer_class_name}"
  non_cached = "NonCached#{serializer_class_name}"
  cached_serializer     = get_or_create_serializer(cached)
  non_cached_serializer = get_or_create_serializer(non_cached)
  klass._cache_options ||= {}
  cache_key = klass._cache_key
  klass._cache_options[:key] = cache_key if cache_key
  cached_serializer.cache(klass._cache_options)
  type = klass._type
  cached_serializer.type(type)
  non_cached_serializer.type(type)
  non_cached_serializer.fragmented(serializer)
  cached_serializer.fragmented(serializer)
  serializers = { cached: cached_serializer, non_cached: non_cached_serializer }
  cache_attributes(serializers)
  serializers
end

def get_or_create_serializer(name)

def get_or_create_serializer(name)
  return Object.const_get(name) if Object.const_defined?(name)
  Object.const_set(name, Class.new(ActiveModel::Serializer))
end

def initialize(adapter, serializer, options)

def initialize(adapter, serializer, options)
  @instance_options = options
  @adapter    = adapter
  @serializer = serializer
end

def serialize(object, serializer_class)

def serialize(object, serializer_class)
  SerializableResource.new(
    object,
    serializer: serializer_class,
    adapter: adapter.class
  ).serializable_hash
end

def to_valid_const_name(name)

def to_valid_const_name(name)
  name.gsub('::', '_')
end