class Cattri::AttributeCompiler

memoization and validation of default values for final attributes.
Handles both instance and class-level attributes, including
- explicit writers (‘:name=` methods)
- predicate methods
- callable accessors (acting as both reader and writer)
This includes:
based on the metadata in a {Cattri::Attribute}.
Responsible for defining methods on the target class/module
@internal

def define_accessor(attribute, context)

Returns:
  • (void) -

Parameters:
  • context (Cattri::Context) -- the target context for method definition
  • attribute (Cattri::Attribute) -- the attribute to define
def define_accessor(attribute, context)
  if attribute.class_attribute? && attribute.final?
    value = attribute.evaluate_default
    context.target.cattri_variable_set(attribute.ivar, value) # steep:ignore
  end
  return if attribute.expose == :none
  define_accessor!(attribute, context)
  define_writer!(attribute, context)
  define_predicate!(attribute, context) if attribute.with_predicate?
end

def define_accessor!(attribute, context)

Returns:
  • (void) -

Parameters:
  • context (Cattri::Context) --
  • attribute (Cattri::Attribute) --
def define_accessor!(attribute, context)
  context.define_method(attribute) do |*args, **kwargs|
    readonly_call = args.empty? && kwargs.empty?
    return AttributeCompiler.send(:memoize_default_value, self, attribute) if readonly_call
    attribute.validate_assignment!
    value = attribute.process_assignment(*args, **kwargs)
    cattri_variable_set(attribute.ivar, value) # steep:ignore
  end
end

def define_predicate!(attribute, context)

Returns:
  • (void) -

Parameters:
  • context (Cattri::Context) --
  • attribute (Cattri::Attribute) --
def define_predicate!(attribute, context)
  context.define_method(attribute, name: :"#{attribute.name}?") do
    !!send(attribute.name) # rubocop:disable Style/DoubleNegation
  end
end

def define_writer!(attribute, context)

Returns:
  • (void) -

Parameters:
  • context (Cattri::Context) --
  • attribute (Cattri::Attribute) --
def define_writer!(attribute, context)
  context.define_method(attribute, name: :"#{attribute.name}=") do |value|
    coerced_value = attribute.process_assignment(value)
    cattri_variable_set(attribute.ivar, coerced_value, final: attribute.final?) # steep:ignore
  end
end

def memoize_default_value(receiver, attribute)

Raises:
  • (Cattri::AttributeError) - if final attribute is unset or evaluation fails

Returns:
  • (Object) - the stored or evaluated default

Parameters:
  • attribute (Cattri::Attribute) --
  • receiver (Object) -- the instance or class receiving the value
def memoize_default_value(receiver, attribute)
  if attribute.final?
    return receiver.cattri_variable_get(attribute.ivar) if receiver.cattri_variable_defined?(attribute.ivar)
    raise Cattri::AttributeError, "Final attribute :#{attribute.name} cannot be written to"
  end
  receiver.cattri_variable_memoize(attribute.ivar, final: attribute.final?) do
    attribute.evaluate_default
  end
end