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)
-
(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)
-
(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)
-
(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)
-
(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)
-
(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