Class: Cattri::Attribute
- Inherits:
-
Object
- Object
- Cattri::Attribute
- Defined in:
- lib/cattri/attribute.rb
Overview
Attribute acts as a thin wrapper around AttributeOptions, exposing core attribute metadata and behavior in a safe, immutable way.
Each Attribute instance represents a single logical property, and delegates its behavior (default, visibility, coercion, etc.) to its associated AttributeOptions.
Instance Attribute Summary collapse
-
#default ⇒ Proc
readonly
A callable lambda for the attribute’s default value.
-
#defined_in ⇒ Module
readonly
The class or module this attribute was defined in.
-
#expose ⇒ Symbol
readonly
Method exposure type (:read, :write, :read_write, or :none).
-
#ivar ⇒ Symbol
readonly
The backing instance variable (e.g., :@enabled).
-
#name ⇒ Symbol
readonly
The canonical name of the attribute.
-
#transformer ⇒ Proc
readonly
A callable transformer used to process assigned values.
-
#visibility ⇒ Symbol
readonly
Method visibility (:public, :protected, :private).
Instance Method Summary collapse
-
#allowed_methods ⇒ Array<Symbol>
Returns the methods that will be defined for this attribute.
-
#class_attribute? ⇒ Boolean
Whether the attribute is class-level.
-
#evaluate_default ⇒ Object
Resolves the default value for this attribute.
-
#final? ⇒ Boolean
Whether the attribute is marked final (write-once).
-
#initialize(name, defined_in:, **options, &transformer) ⇒ Attribute
constructor
Initializes a new attribute definition.
-
#internal_reader? ⇒ Boolean
Whether the reader should remain internal.
-
#internal_writer? ⇒ Boolean
Whether the writer should remain internal.
-
#process_assignment(*args, **kwargs) ⇒ Object
Processes and transforms an incoming assignment for this attribute.
-
#readable? ⇒ Boolean
Whether the attribute allows reading.
-
#readonly? ⇒ Boolean
Whether the attribute is marked readonly.
-
#to_h ⇒ Hash<Symbol, Object>
Serializes this attribute and its configuration to a frozen hash.
-
#validate_assignment! ⇒ Object
Validates whether this attribute is assignable in the current context.
-
#with_predicate? ⇒ Boolean
Whether the attribute defines a predicate method (
:name?). -
#writable? ⇒ Boolean
Whether the attribute should define a writer (public or internal).
Constructor Details
#initialize(name, defined_in:, **options, &transformer) ⇒ Attribute
Initializes a new attribute definition.
30 31 32 33 |
# File 'lib/cattri/attribute.rb', line 30 def initialize(name, defined_in:, **, &transformer) = Cattri::AttributeOptions.new(name, transformer: transformer, **) @defined_in = defined_in end |
Instance Attribute Details
#default ⇒ Proc (readonly)
Returns a callable lambda for the attribute’s default value.
|
|
# File 'lib/cattri/attribute.rb', line 59
|
#defined_in ⇒ Module (readonly)
Returns the class or module this attribute was defined in.
21 22 23 |
# File 'lib/cattri/attribute.rb', line 21 def defined_in @defined_in end |
#expose ⇒ Symbol (readonly)
Returns method exposure type (:read, :write, :read_write, or :none).
|
|
# File 'lib/cattri/attribute.rb', line 65
|
#ivar ⇒ Symbol (readonly)
Returns the backing instance variable (e.g., :@enabled).
|
|
# File 'lib/cattri/attribute.rb', line 56
|
#name ⇒ Symbol (readonly)
Returns the canonical name of the attribute.
|
|
# File 'lib/cattri/attribute.rb', line 53
|
#transformer ⇒ Proc (readonly)
Returns a callable transformer used to process assigned values.
|
|
# File 'lib/cattri/attribute.rb', line 62
|
#visibility ⇒ Symbol (readonly)
Returns method visibility (:public, :protected, :private).
71 72 73 74 75 76 77 78 79 80 |
# File 'lib/cattri/attribute.rb', line 71 i[ name ivar default transformer expose visibility ].each do |option| define_method(option) { .public_send(option) } end |
Instance Method Details
#allowed_methods ⇒ Array<Symbol>
Returns the methods that will be defined for this attribute.
Includes the base accessor, optional writer, and optional predicate.
131 132 133 |
# File 'lib/cattri/attribute.rb', line 131 def allowed_methods [name, (:"#{name}=" if writable?), (:"#{name}?" if with_predicate?)].compact.freeze end |
#class_attribute? ⇒ Boolean
Returns whether the attribute is class-level.
117 118 119 |
# File 'lib/cattri/attribute.rb', line 117 def class_attribute? .scope == :class end |
#evaluate_default ⇒ Object
Resolves the default value for this attribute.
150 151 152 153 154 |
# File 'lib/cattri/attribute.rb', line 150 def evaluate_default .default.call rescue StandardError => e raise Cattri::AttributeError, "Failed to evaluate the default value for `:#{@options.name}`. Error: #{e.message}" end |
#final? ⇒ Boolean
Returns whether the attribute is marked final (write-once).
112 113 114 |
# File 'lib/cattri/attribute.rb', line 112 def final? .final end |
#internal_reader? ⇒ Boolean
Returns whether the reader should remain internal.
83 84 85 |
# File 'lib/cattri/attribute.rb', line 83 def internal_reader? i[write none].include?(.expose) end |
#internal_writer? ⇒ Boolean
Returns whether the writer should remain internal.
88 89 90 |
# File 'lib/cattri/attribute.rb', line 88 def internal_writer? i[read none].include?(.expose) end |
#process_assignment(*args, **kwargs) ⇒ Object
Processes and transforms an incoming assignment for this attribute.
162 163 164 165 166 |
# File 'lib/cattri/attribute.rb', line 162 def process_assignment(*args, **kwargs) .transformer.call(*args, **kwargs) rescue StandardError => e raise Cattri::AttributeError, "Failed to evaluate the setter for `:#{@options.name}`. Error: #{e.message}" end |
#readable? ⇒ Boolean
Returns whether the attribute allows reading.
93 94 95 |
# File 'lib/cattri/attribute.rb', line 93 def readable? i[read read_write].include?(.expose) end |
#readonly? ⇒ Boolean
Returns whether the attribute is marked readonly.
105 106 107 108 109 |
# File 'lib/cattri/attribute.rb', line 105 def readonly? return false if .expose == :none .expose == :read end |
#to_h ⇒ Hash<Symbol, Object>
Serializes this attribute and its configuration to a frozen hash.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/cattri/attribute.rb', line 38 def to_h { name: .name, ivar: .ivar, defined_in: @defined_in, final: .final, scope: .scope, predicate: .predicate, default: .default, transformer: .transformer, expose: .expose, visibility: .visibility } end |
#validate_assignment! ⇒ Object
Validates whether this attribute is assignable in the current context.
138 139 140 141 142 143 144 |
# File 'lib/cattri/attribute.rb', line 138 def validate_assignment! if final? raise Cattri::AttributeError, "Cannot assign to final attribute `:#{name}`" elsif readonly? raise Cattri::AttributeError, "Cannot assign to readonly attribute `:#{name}`" end end |
#with_predicate? ⇒ Boolean
Returns whether the attribute defines a predicate method (:name?).
122 123 124 |
# File 'lib/cattri/attribute.rb', line 122 def with_predicate? .predicate end |
#writable? ⇒ Boolean
Returns whether the attribute should define a writer (public or internal).
98 99 100 101 102 |
# File 'lib/cattri/attribute.rb', line 98 def writable? return false if .expose == :none !readonly? || internal_writer? end |