class CacheCrispies::Base

The Base class that all serializer classes should inherit from

Attributes

attributes[R]
model[R]
options[R]

Public Class Methods

cache_key_addons(options = {}, &block) click to toggle source

Call with a block returning an array of strings that should be added to the cache key for an instance of this serializer. Typically you'd add in string values to uniquely represent the values you're passing to the serializer so that they are cached separately. But it could also contain any custom logic about how to construct a cache key. Call without a block to act as a getter and return the value.

@example cache based off models provided in options

cache_key_addons { |options| [options[:current_user].id] }

@example time-based caching

cache_key_addons { |_options| [Date.today.to_s] }

@param options [Hash] the options hash passed to the serializer, will be passed in here as well so you can refernce it if needed. @yield [options] a block that takes options passed to the serializer and should return an array of strings to use in the cache key @return [Array<String>]

# File lib/cache_crispies/base.rb, line 131
def self.cache_key_addons(options = {}, &block)
  @cache_key_addons ||= nil

  if block_given?
    @cache_key_addons = block
    nil
  else
    Array(@cache_key_addons&.call(options))
  end
end
cache_key_base() click to toggle source

Return a cache key string for the serializer class to be included in the cache key for the instances. The key includes the name of the class, and a digest of the contents of the main class file.

@return [String] a cache key for the class

# File lib/cache_crispies/base.rb, line 165
def self.cache_key_base
  @cache_key_base ||= "#{self}-#{file_hashes.join(CACHE_KEY_SEPARATOR)}"
end
collection_key(*key) click to toggle source

Get or set a JSON key to use as a root key on a collection-type serializable. By deafult it's the plural version of .key, but it can be overridden in a subclass to be anything. Calling the method with a key will set the key, calling it without any arguments will get the key.

@return [Symbol] a symbol to be used as a key for a JSON-ready Hash @param key [Symbol, nil] a symbol to be used as a key for a JSON-ready Hash, or nil for no key @return [Symbol, nil] a symbol to be used as a key for a JSON-ready Hash, or nil for no key

# File lib/cache_crispies/base.rb, line 97
def self.collection_key(*key)
  @default_collection_key ||= self.key.to_s.pluralize.to_sym

  # method called with no args so act as a getter
  if key.empty?
    if defined? @collection_key
      return @collection_key
    else
      return @default_collection_key
    end
  end

  # method called with args so act as a setter
  @collection_key = key.first&.to_sym
end
dependency_key(key = nil) click to toggle source

Get or set a cache key that can be changed whenever an outside dependency of any kind changes in any way that could change the output of your serializer. For instance, if a mixin is changed. Or maybe an object you're serializing has changed it's to_json method. This key should be changed accordingly, to bust the cache so that you're not serving stale data.

@return [String] a version string in any form

# File lib/cache_crispies/base.rb, line 150
def self.dependency_key(key = nil)
  @dependency_key ||= nil

  # method called with no args so act as a getter
  return @dependency_key unless key

  # method called with args so act as a setter
  @dependency_key = key.to_s
end
do_caching(value = nil) click to toggle source

Get or set whether or not this serializer class should allow caching of results. It returns false by default, but can be overridden in child classes. Calling the method with an argument will set the value, calling it without any arguments will get the value.

@param value [Boolean] true to enable caching, false to disable @return [Boolean]

# File lib/cache_crispies/base.rb, line 53
def self.do_caching(value = nil)
  @do_caching ||= false

  # method called with no args so act as a getter
  return @do_caching if value.nil?

  # method called with args so act as a setter
  @do_caching = !!value
end
Also aliased as: do_caching?
do_caching?(value = nil)
Alias for: do_caching
file_hashes() click to toggle source

Return an array of cache key string for this serializer and all nested and deeply nested serializers. The purpose of grabbing all this data is to be able to construct a cache key that will be busted if any of the nested serializers, no matter how deep, change at all.

@return [Array<String>] an array of uniq, sorted serializer file hashes

# File lib/cache_crispies/base.rb, line 175
def self.file_hashes
  @file_hashes ||= (
    [file_hash] + nested_serializers.flat_map(&:file_hashes)
  ).uniq.sort
end
inherited(other) click to toggle source

Define class-level instance variables and their default values when the class is inherited by another class. This is not meant to be called directly. It is called internally by Ruby.

@param other [Class] the inheriting child class @return [void]

# File lib/cache_crispies/base.rb, line 17
def self.inherited(other)
  other.instance_variable_set(:@attributes, [])
  other.instance_variable_set(:@nesting, [])
  other.instance_variable_set(:@conditions, [])
end
key(*key) click to toggle source

Get or set a JSON key to use as a root key on a non-collection serializable. By default it's the name of the class without the “Serializer” part. But it can be overridden in a subclass to be anything. Calling the method with a key will set the key, calling it without any arguments will get the key.

@param key [Symbol, nil] a symbol to be used as a key for a JSON-ready Hash, or nil for no key @return [Symbol, nil] a symbol to be used as a key for a JSON-ready Hash, or nil for no key

# File lib/cache_crispies/base.rb, line 77
def self.key(*key)
  @default_key ||= to_s.demodulize.chomp('Serializer').underscore.to_sym

  # method called with no args so act as a getter
  return defined?(@key) ? @key : @default_key if key.empty?

  # method called with args so act as a setter
  @key = key.first&.to_sym
end
new(model, options = {}) click to toggle source

Initializes a new instance of CacheCrispies::Base, or really, it should always be a subclass of CacheCrispies::Base.

@param model [Object] typically ActiveRecord::Base, but could be anything @param options [Hash] any optional custom values you want to be

accessible in your subclass.
# File lib/cache_crispies/base.rb, line 34
def initialize(model, options = {})
  @model = model
  @options = options
end

Private Class Methods

file_hash() click to toggle source
# File lib/cache_crispies/base.rb, line 183
def self.file_hash
  @file_hash ||= Digest::MD5.file(path).to_s
end
merge(attribute = nil, with: nil) click to toggle source
# File lib/cache_crispies/base.rb, line 249
def self.merge(attribute = nil, with: nil)
  serialize(nil, from: attribute, with: with)
end
nest_in(key, &block) click to toggle source
# File lib/cache_crispies/base.rb, line 198
def self.nest_in(key, &block)
  @nesting << key

  block.call

  @nesting.pop
end
nested_serializers() click to toggle source
# File lib/cache_crispies/base.rb, line 216
def self.nested_serializers
  attributes.map(&:serializer).compact
end
path() click to toggle source
# File lib/cache_crispies/base.rb, line 188
def self.path
  @path ||= begin
    parts = %w[app serializers]
    parts += to_s.deconstantize.split('::').map(&:underscore)
    parts << "#{to_s.demodulize.underscore}.rb"
    Rails.root.join(*parts)
  end
end
serialize( *attribute_names, from: nil, with: nil, through: nil, to: nil, collection: nil, optional: nil, &block ) click to toggle source
# File lib/cache_crispies/base.rb, line 221
def self.serialize(
  *attribute_names,
  from: nil, with: nil, through: nil, to: nil, collection: nil,
  optional: nil,
  &block
)
  attribute_names.flat_map do |attrib|
    attrib = attrib&.to_sym
    current_nesting = Array(@nesting).dup
    current_conditions = Array(@conditions).dup

    @attributes <<
      Attribute.new(
        attrib,
        from: from,
        with: with,
        through: through,
        to: to,
        collection: collection,
        optional: optional,
        nesting: current_nesting,
        conditions: current_conditions,
        &block
      )
  end
end
show_if(condition_proc, &block) click to toggle source
# File lib/cache_crispies/base.rb, line 207
def self.show_if(condition_proc, &block)
  @conditions << Condition.new(condition_proc)

  block.call

  @conditions.pop
end

Public Instance Methods

as_json() click to toggle source

Renders the serializer instance to a JSON-ready Hash

@return [Hash] a JSON-ready hash

# File lib/cache_crispies/base.rb, line 42
def as_json
  HashBuilder.new(self).call
end