class CacheCrispies::Attribute

Reperesents a single serialized attribute in a serializer. It's generated by a call to either {CacheCrispies::Base.serialize} or {CacheCrispies::Base.merge}.

Attributes

block[R]
coerce_to[R]
collection[R]
conditions[R]
key[R]
method_name[R]
nesting[R]
serializer[R]
through[R]

Public Class Methods

new( key, from: nil, with: nil, through: nil, to: nil, collection: nil, optional: nil, nesting: [], conditions: [], &block ) click to toggle source

Initializes a new CacheCrispies::Attribute instance

@param key [Symbol] the JSON key for this attribute @param from [Symbol] the method on the model to call to get the value @param with [CacheCrispies::Base] a serializer to use to serialize the @param to [Class, Symbol] the data type to coerce the value into @param collection [Boolean] force rendering as single or collection @param optional [Boolean] render only if included in the option's

`included` array

@param nesting [Array<Symbol>] the JSON keys this attribute will be

nested inside

@param conditions [Array<CacheCrispies::Condition>] the show_if condition

blocks this attribute is nested inside. These will be evaluated for
thruthiness and must all be true for this attribute to reneder.
argument's value
# File lib/cache_crispies/attribute.rb, line 26
def initialize(
  key,
  from: nil, with: nil, through: nil, to: nil, collection: nil,
  optional: nil,
  nesting: [], conditions: [],
  &block
)
  @key = key
  @method_name = from || key || :itself
  @serializer = with
  @through = through
  @coerce_to = to
  @collection = collection
  @nesting = Array(nesting)
  @conditions = Array(conditions)
  @block = block

  @conditions << Optional.new(key) if optional
end

Public Instance Methods

value_for(target, options) click to toggle source

Gets the value of the attribute for the given target object and options

@param target [Object] typically ActiveRecord::Base, but could be anything @param options [Hash] any optional values from the serializer instance @return the value for the attribute for the given model and options @raise [InvalidCoercionType] when an invalid argument is passed in the

to: argument
# File lib/cache_crispies/attribute.rb, line 65
def value_for(target, options)
  value =
    if block?
      block.call(target, options)
    elsif through?
      target.public_send(through)&.public_send(method_name)
    else
      target.public_send(method_name)
    end

  serializer ? serialize(value, options) : coerce(value)
end

Private Instance Methods

block?() click to toggle source
# File lib/cache_crispies/attribute.rb, line 84
def block?
  !block.nil?
end
coerce(value) click to toggle source
# File lib/cache_crispies/attribute.rb, line 102
def coerce(value)
  return value if coerce_to.nil?

  case coerce_to.to_s.to_sym
  when :String
    value.to_s
  when :Integer
    try_coerce_via_string(value, :to_i)
  when :Float
    try_coerce_via_string(value, :to_f)
  when :BigDecimal
    BigDecimal(value)
  when :Array
    Array(value)
  when :Hash
    value.respond_to?(:to_h) ? value.to_h : value.to_hash
  when :bool, :boolean, :TrueClass, :FalseClass
    !!value
  else
    raise(
      InvalidCoercionType,
      "#{coerce_to} has no registered coercion strategy"
    )
  end
end
serialize(value, options) click to toggle source

Here we'll render the attribute with a given serializer and attempt to cache the results for better cache reusability

# File lib/cache_crispies/attribute.rb, line 90
def serialize(value, options)
  plan = CacheCrispies::Plan.new(
    serializer, value, collection: collection, **options
  )

  if plan.collection?
    plan.cache { Collection.new(value, serializer, options).as_json }
  else
    plan.cache { serializer.new(value, options).as_json }
  end
end
through?() click to toggle source
# File lib/cache_crispies/attribute.rb, line 80
def through?
  !through.nil?
end
try_coerce_via_string(value, method_name) click to toggle source
# File lib/cache_crispies/attribute.rb, line 128
def try_coerce_via_string(value, method_name)
  (
    value.respond_to?(method_name) ? value : value.to_s
  ).public_send(method_name)
end