domainic-attributer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +14 -0
- data/LICENSE +21 -0
- data/README.md +396 -0
- data/lib/domainic/attributer/attribute/callback.rb +68 -0
- data/lib/domainic/attributer/attribute/coercer.rb +93 -0
- data/lib/domainic/attributer/attribute/mixin/belongs_to_attribute.rb +68 -0
- data/lib/domainic/attributer/attribute/signature.rb +338 -0
- data/lib/domainic/attributer/attribute/validator.rb +128 -0
- data/lib/domainic/attributer/attribute.rb +256 -0
- data/lib/domainic/attributer/attribute_set.rb +208 -0
- data/lib/domainic/attributer/class_methods.rb +247 -0
- data/lib/domainic/attributer/dsl/attribute_builder/option_parser.rb +247 -0
- data/lib/domainic/attributer/dsl/attribute_builder.rb +233 -0
- data/lib/domainic/attributer/dsl/initializer.rb +130 -0
- data/lib/domainic/attributer/dsl/method_injector.rb +97 -0
- data/lib/domainic/attributer/dsl.rb +5 -0
- data/lib/domainic/attributer/instance_methods.rb +65 -0
- data/lib/domainic/attributer/undefined.rb +44 -0
- data/lib/domainic/attributer.rb +114 -0
- data/lib/domainic-attributer.rb +3 -0
- data/sig/domainic/attributer/attribute/callback.rbs +48 -0
- data/sig/domainic/attributer/attribute/coercer.rbs +59 -0
- data/sig/domainic/attributer/attribute/mixin/belongs_to_attribute.rbs +46 -0
- data/sig/domainic/attributer/attribute/signature.rbs +223 -0
- data/sig/domainic/attributer/attribute/validator.rbs +83 -0
- data/sig/domainic/attributer/attribute.rbs +150 -0
- data/sig/domainic/attributer/attribute_set.rbs +134 -0
- data/sig/domainic/attributer/class_methods.rbs +151 -0
- data/sig/domainic/attributer/dsl/attribute_builder/option_parser.rbs +130 -0
- data/sig/domainic/attributer/dsl/attribute_builder.rbs +156 -0
- data/sig/domainic/attributer/dsl/initializer.rbs +91 -0
- data/sig/domainic/attributer/dsl/method_injector.rbs +66 -0
- data/sig/domainic/attributer/dsl.rbs +1 -0
- data/sig/domainic/attributer/instance_methods.rbs +53 -0
- data/sig/domainic/attributer/undefined.rbs +14 -0
- data/sig/domainic/attributer.rbs +69 -0
- data/sig/domainic-attributer.rbs +1 -0
- data/sig/manifest.yaml +2 -0
- metadata +89 -0
@@ -0,0 +1,134 @@
|
|
1
|
+
module Domainic
|
2
|
+
module Attributer
|
3
|
+
# A class representing an ordered collection of attributes.
|
4
|
+
#
|
5
|
+
# This class manages a set of attributes for a given class or module. It maintains
|
6
|
+
# attributes in a specific order determined by their type (argument vs option),
|
7
|
+
# default values, and position. The collection supports standard operations like
|
8
|
+
# adding, selecting, and merging attributes while maintaining proper ownership
|
9
|
+
# relationships with their base class.
|
10
|
+
#
|
11
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
12
|
+
# @since 0.1.0
|
13
|
+
class AttributeSet
|
14
|
+
extend Forwardable
|
15
|
+
|
16
|
+
@base: __todo__
|
17
|
+
|
18
|
+
@lookup: Hash[Symbol, Attribute]
|
19
|
+
|
20
|
+
# Initialize a new AttributeSet.
|
21
|
+
#
|
22
|
+
# @param base [Class, Module] the class or module this set belongs to
|
23
|
+
# @param attributes [Array<Attribute>] initial attributes to add
|
24
|
+
#
|
25
|
+
# @return [void]
|
26
|
+
def initialize: (__todo__ base, ?Array[Attribute] attributes) -> void
|
27
|
+
|
28
|
+
# Get an attribute by name.
|
29
|
+
#
|
30
|
+
# @param attribute_name [String, Symbol] the name of the attribute
|
31
|
+
#
|
32
|
+
# @return [Attribute, nil] the attribute if found
|
33
|
+
def []: (String | Symbol attribute_name) -> Attribute?
|
34
|
+
|
35
|
+
# Add an attribute to the set.
|
36
|
+
#
|
37
|
+
# If an attribute with the same name exists, the attributes are merged.
|
38
|
+
# If the attribute belongs to a different base class, it is duplicated
|
39
|
+
# with the correct base. After adding, attributes are sorted by type
|
40
|
+
# and position.
|
41
|
+
#
|
42
|
+
# @param attribute [Attribute] the attribute to add
|
43
|
+
#
|
44
|
+
# @raise [ArgumentError] if attribute is invalid
|
45
|
+
# @return [void]
|
46
|
+
def add: (Attribute attribute) -> void
|
47
|
+
|
48
|
+
# Check if an attribute exists in the set.
|
49
|
+
#
|
50
|
+
# @param attribute_name [String, Symbol] the name to check
|
51
|
+
#
|
52
|
+
# @return [Boolean] true if the attribute exists
|
53
|
+
def attribute?: (untyped attribute_name) -> untyped
|
54
|
+
|
55
|
+
# Get all attribute names.
|
56
|
+
#
|
57
|
+
# @return [Array<Symbol>] the attribute names
|
58
|
+
def attribute_names: () -> Array[Symbol]
|
59
|
+
|
60
|
+
# Get all attributes.
|
61
|
+
#
|
62
|
+
# @return [Array<Attribute>] the attributes
|
63
|
+
def attributes: () -> Array[Attribute]
|
64
|
+
|
65
|
+
def count: () ?{ (Symbol, Attribute) -> boolish } -> Integer
|
66
|
+
|
67
|
+
# Create a duplicate set for a new base class.
|
68
|
+
#
|
69
|
+
# @param new_base [Class, Module] the new base class
|
70
|
+
#
|
71
|
+
# @return [AttributeSet] the duplicated set
|
72
|
+
def dup_with_base: (__todo__ base) -> AttributeSet
|
73
|
+
|
74
|
+
# Iterate over attribute name/value pairs.
|
75
|
+
#
|
76
|
+
# @yield [name, attribute] each name/attribute pair
|
77
|
+
# @yieldparam name [Symbol] the attribute name
|
78
|
+
# @yieldparam attribute [Attribute] the attribute
|
79
|
+
#
|
80
|
+
# @return [self]
|
81
|
+
def each: () { ([ Symbol, Attribute ]) -> untyped } -> self
|
82
|
+
|
83
|
+
alias each_pair each
|
84
|
+
|
85
|
+
def empty?: () -> bool
|
86
|
+
|
87
|
+
# Create a new set excluding specified attributes.
|
88
|
+
#
|
89
|
+
# @param attribute_names [Array<String, Symbol>] names to exclude
|
90
|
+
#
|
91
|
+
# @return [AttributeSet] new set without specified attributes
|
92
|
+
def except: (*String | Symbol attribute_names) -> AttributeSet
|
93
|
+
|
94
|
+
def length: () -> Integer
|
95
|
+
|
96
|
+
# Merge another set into this one.
|
97
|
+
#
|
98
|
+
# @param other [AttributeSet] the set to merge
|
99
|
+
#
|
100
|
+
# @return [AttributeSet] new set with merged attributes
|
101
|
+
def merge: (AttributeSet other) -> AttributeSet
|
102
|
+
|
103
|
+
# Create a new set with rejected attributes.
|
104
|
+
#
|
105
|
+
# @yield [name, attribute] each name/attribute pair
|
106
|
+
# @yieldparam name [Symbol] the attribute name
|
107
|
+
# @yieldparam attribute [Attribute] the attribute
|
108
|
+
#
|
109
|
+
# @return [AttributeSet] new set without rejected attributes
|
110
|
+
def reject: () { (Symbol, Attribute) -> boolish } -> AttributeSet
|
111
|
+
|
112
|
+
# Create a new set with selected attributes.
|
113
|
+
#
|
114
|
+
# @yield [name, attribute] each name/attribute pair
|
115
|
+
# @yieldparam name [Symbol] the attribute name
|
116
|
+
# @yieldparam attribute [Attribute] the attribute
|
117
|
+
#
|
118
|
+
# @return [AttributeSet] new set with selected attributes
|
119
|
+
def select: () { (Symbol, Attribute) -> boolish } -> AttributeSet
|
120
|
+
|
121
|
+
def size: () -> Integer
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
# Sort attributes by type and position.
|
126
|
+
#
|
127
|
+
# Attributes are sorted first by type (required arguments, defaulted arguments,
|
128
|
+
# then options), and then by their position within those groups.
|
129
|
+
#
|
130
|
+
# @return [void]
|
131
|
+
def sort_lookup: () -> void
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
module Domainic
|
2
|
+
module Attributer
|
3
|
+
# A module providing class-level methods for attribute definition.
|
4
|
+
#
|
5
|
+
# This module extends classes that include Domainic::Attributer with methods for
|
6
|
+
# defining and managing attributes. It supports two types of attributes:
|
7
|
+
# 1. Arguments - Positional parameters that must be provided in a specific order
|
8
|
+
# 2. Options - Named parameters that can be provided in any order
|
9
|
+
#
|
10
|
+
# @example Defining arguments and options
|
11
|
+
# class Person
|
12
|
+
# include Domainic::Attributer
|
13
|
+
#
|
14
|
+
# argument :name, ->(value) { value.is_a?(String) }
|
15
|
+
# argument :age do |value|
|
16
|
+
# value.is_a?(Integer) && value >= 0
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# option :email, ->(value) { value.is_a?(String) }, default: nil
|
20
|
+
# option :role do |value|
|
21
|
+
# %w[admin user guest].include?(value)
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
26
|
+
# @since 0.1.0
|
27
|
+
module ClassMethods
|
28
|
+
@__attributes__: AttributeSet
|
29
|
+
|
30
|
+
# Define a positional argument attribute.
|
31
|
+
#
|
32
|
+
# Arguments are required by default and must be provided in the order they are defined.
|
33
|
+
# They can be type-validated and configured with additional options like defaults
|
34
|
+
# and visibility.
|
35
|
+
#
|
36
|
+
# @param attribute_name [String, Symbol] the name of the attribute
|
37
|
+
# @param type_validator [Proc, Object, nil] optional validation handler for type checking
|
38
|
+
# @param options [Hash] additional configuration options
|
39
|
+
#
|
40
|
+
# @option options [Array<Proc>, Proc] :callbacks handlers for attribute change events (priority over :callback,
|
41
|
+
# :on_change)
|
42
|
+
# @option options [Array<Proc>, Proc] :callback alias for :callbacks
|
43
|
+
# @option options [Array<Proc, Symbol>, Proc, Symbol] :coerce handlers for value coercion (priority over
|
44
|
+
# :coercers, :coerce_with)
|
45
|
+
# @option options [Array<Proc, Symbol>, Proc, Symbol] :coercers alias for :coerce
|
46
|
+
# @option options [Array<Proc, Symbol>, Proc, Symbol] :coerce_with alias for :coerce
|
47
|
+
# @option options [Object] :default the default value (priority over :default_generator, :default_value)
|
48
|
+
# @option options [Object] :default_generator alias for :default
|
49
|
+
# @option options [Object] :default_value alias for :default
|
50
|
+
# @option options [String] :desc short description (overridden by :description)
|
51
|
+
# @option options [String] :description description text
|
52
|
+
# @option options [Boolean] :non_nil require non-nil values (priority over :non_null, :non_nullable, :not_nil,
|
53
|
+
# :not_nilable, :not_null, :not_nullable)
|
54
|
+
# @option options [Boolean] :non_null alias for :non_nil
|
55
|
+
# @option options [Boolean] :non_nullable alias for :non_nil
|
56
|
+
# @option options [Boolean] :not_nil alias for :non_nil
|
57
|
+
# @option options [Boolean] :not_nilable alias for :non_nil
|
58
|
+
# @option options [Boolean] :not_null alias for :non_nil
|
59
|
+
# @option options [Boolean] :not_nullable alias for :non_nil
|
60
|
+
# @option options [Boolean] :null inverse of :non_nil
|
61
|
+
# @option options [Array<Proc>, Proc] :on_change alias for :callbacks
|
62
|
+
# @option options [Boolean] :optional whether attribute is optional (overridden by :required)
|
63
|
+
# @option options [Integer] :position specify order position
|
64
|
+
# @option options [Symbol] :read read visibility (:public, :protected, :private) (priority over :read_access,
|
65
|
+
# :reader)
|
66
|
+
# @option options [Symbol] :read_access alias for :read
|
67
|
+
# @option options [Symbol] :reader alias for :read
|
68
|
+
# @option options [Boolean] :required whether attribute is required
|
69
|
+
# @option options [Array<Object>, Object] :validate validators for the attribute (priority over :validate_with,
|
70
|
+
# :validators)
|
71
|
+
# @option options [Array<Object>, Object] :validate_with alias for :validate
|
72
|
+
# @option options [Array<Object>, Object] :validators alias for :validate
|
73
|
+
# @option options [Symbol] :write_access write visibility (:public, :protected, :private) (priority over :writer)
|
74
|
+
# @option options [Symbol] :writer alias for :write_access
|
75
|
+
#
|
76
|
+
# @yield [DSL::AttributeBuilder] optional configuration block
|
77
|
+
# @return [void]
|
78
|
+
def argument: (String | Symbol attribute_name, ?Attribute::Validator::handler type_validator, ?callbacks: Array[Attribute::Callback::handler] | Attribute::Callback::handler, ?callback: Array[Attribute::Callback::handler] | Attribute::Callback::handler, ?coerce: Array[Attribute::Coercer::handler] | Attribute::Coercer::handler, ?coercers: Array[Attribute::Coercer::handler], ?coerce_with: [ Attribute::Coercer::handler ] | Attribute::Coercer::handler, ?default: untyped, ?default_generator: untyped, ?default_value: untyped, ?desc: String?, ?description: String, ?non_nil: bool, ?non_null: bool, ?non_nullable: bool, ?not_nil: bool, ?not_nilable: bool, ?not_null: bool, ?not_nullable: bool, ?null: bool, ?on_change: Array[Attribute::Callback::handler] | Attribute::Callback::handler, ?optional: bool, ?position: Integer?, ?read: Attribute::Signature::visibility_symbol, ?read_access: Attribute::Signature::visibility_symbol, ?reader: Attribute::Signature::visibility_symbol, ?required: bool, ?validate: Array[Attribute::Validator::handler] | Attribute::Validator::handler, ?validate_with: Array[Attribute::Validator::handler] | Attribute::Validator::handler, ?validators: Array[Attribute::Validator::handler] | Attribute::Validator::handler, ?write_access: Attribute::Signature::visibility_symbol, ?writer: Attribute::Signature::visibility_symbol) ?{ (?) [self: DSL::AttributeBuilder] -> void } -> void
|
79
|
+
|
80
|
+
# Define a named option attribute.
|
81
|
+
#
|
82
|
+
# Options are optional by default and can be provided in any order. They can be
|
83
|
+
# type-validated and configured with additional options like defaults and visibility.
|
84
|
+
#
|
85
|
+
# @overload option(attribute_name, type_validator = Undefined, **options, &block)
|
86
|
+
# @param attribute_name [String, Symbol] the name of the attribute
|
87
|
+
# @param type_validator [Proc, Object, nil] optional validation handler for type checking
|
88
|
+
# @param options [Hash] additional configuration options
|
89
|
+
#
|
90
|
+
# @option options [Array<Proc>, Proc] :callbacks handlers for attribute change events (priority over :callback,
|
91
|
+
# :on_change)
|
92
|
+
# @option options [Array<Proc>, Proc] :callback alias for :callbacks
|
93
|
+
# @option options [Array<Proc, Symbol>, Proc, Symbol] :coerce handlers for value coercion (priority over
|
94
|
+
# :coercers, :coerce_with)
|
95
|
+
# @option options [Array<Proc, Symbol>, Proc, Symbol] :coercers alias for :coerce
|
96
|
+
# @option options [Array<Proc, Symbol>, Proc, Symbol] :coerce_with alias for :coerce
|
97
|
+
# @option options [Object] :default the default value (priority over :default_generator, :default_value)
|
98
|
+
# @option options [Object] :default_generator alias for :default
|
99
|
+
# @option options [Object] :default_value alias for :default
|
100
|
+
# @option options [String] :desc short description (overridden by :description)
|
101
|
+
# @option options [String] :description description text
|
102
|
+
# @option options [Boolean] :non_nil require non-nil values (priority over :non_null, :non_nullable, :not_nil,
|
103
|
+
# :not_nilable, :not_null, :not_nullable)
|
104
|
+
# @option options [Boolean] :non_null alias for :non_nil
|
105
|
+
# @option options [Boolean] :non_nullable alias for :non_nil
|
106
|
+
# @option options [Boolean] :not_nil alias for :non_nil
|
107
|
+
# @option options [Boolean] :not_nilable alias for :non_nil
|
108
|
+
# @option options [Boolean] :not_null alias for :non_nil
|
109
|
+
# @option options [Boolean] :not_nullable alias for :non_nil
|
110
|
+
# @option options [Boolean] :null inverse of :non_nil
|
111
|
+
# @option options [Array<Proc>, Proc] :on_change alias for :callbacks
|
112
|
+
# @option options [Boolean] :optional whether attribute is optional (overridden by :required)
|
113
|
+
# @option options [Integer] :position specify order position
|
114
|
+
# @option options [Symbol] :read read visibility (:public, :protected, :private) (priority over :read_access,
|
115
|
+
# :reader)
|
116
|
+
# @option options [Symbol] :read_access alias for :read
|
117
|
+
# @option options [Symbol] :reader alias for :read
|
118
|
+
# @option options [Boolean] :required whether attribute is required
|
119
|
+
# @option options [Array<Object>, Object] :validate validators for the attribute (priority over :validate_with,
|
120
|
+
# :validators)
|
121
|
+
# @option options [Array<Object>, Object] :validate_with alias for :validate
|
122
|
+
# @option options [Array<Object>, Object] :validators alias for :validate
|
123
|
+
# @option options [Symbol] :write_access write visibility (:public, :protected, :private)
|
124
|
+
# (priority over :writer)
|
125
|
+
# @option options [Symbol] :writer alias for :write_access
|
126
|
+
#
|
127
|
+
# @yield [DSL::AttributeBuilder] optional configuration block
|
128
|
+
# @return [void]
|
129
|
+
#
|
130
|
+
# @yield [DSL::AttributeBuilder] optional configuration block
|
131
|
+
# @return [void]
|
132
|
+
def option: (String | Symbol attribute_name, ?Attribute::Validator::handler type_validator, ?callbacks: Array[Attribute::Callback::handler] | Attribute::Callback::handler, ?callback: Array[Attribute::Callback::handler] | Attribute::Callback::handler, ?coerce: Array[Attribute::Coercer::handler] | Attribute::Coercer::handler, ?coercers: Array[Attribute::Coercer::handler], ?coerce_with: [ Attribute::Coercer::handler ] | Attribute::Coercer::handler, ?default: untyped, ?default_generator: untyped, ?default_value: untyped, ?desc: String?, ?description: String, ?non_nil: bool, ?non_null: bool, ?non_nullable: bool, ?not_nil: bool, ?not_nilable: bool, ?not_null: bool, ?not_nullable: bool, ?null: bool, ?on_change: Array[Attribute::Callback::handler] | Attribute::Callback::handler, ?optional: bool, ?position: Integer?, ?read: Attribute::Signature::visibility_symbol, ?read_access: Attribute::Signature::visibility_symbol, ?reader: Attribute::Signature::visibility_symbol, ?required: bool, ?validate: Array[Attribute::Validator::handler] | Attribute::Validator::handler, ?validate_with: Array[Attribute::Validator::handler] | Attribute::Validator::handler, ?validators: Array[Attribute::Validator::handler] | Attribute::Validator::handler, ?write_access: Attribute::Signature::visibility_symbol, ?writer: Attribute::Signature::visibility_symbol) ?{ (?) [self: DSL::AttributeBuilder] -> void } -> void
|
133
|
+
|
134
|
+
private
|
135
|
+
|
136
|
+
# Handle class inheritance for attributes.
|
137
|
+
#
|
138
|
+
# Ensures that subclasses inherit a copy of their parent's attributes while
|
139
|
+
# maintaining proper ownership relationships.
|
140
|
+
#
|
141
|
+
# @param subclass [Class] the inheriting class
|
142
|
+
# @return [void]
|
143
|
+
def inherited: (Class | Module subclass) -> void
|
144
|
+
|
145
|
+
# Get the attribute set for this class.
|
146
|
+
#
|
147
|
+
# @return [AttributeSet] the set of attributes defined for this class
|
148
|
+
def __attributes__: () -> AttributeSet
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
module Domainic
|
2
|
+
module Attributer
|
3
|
+
module DSL
|
4
|
+
class AttributeBuilder
|
5
|
+
# A class responsible for parsing and normalizing attribute options.
|
6
|
+
#
|
7
|
+
# This class handles the conversion of flexible DSL options into a normalized
|
8
|
+
# format for attribute creation. It supports multiple ways of specifying common
|
9
|
+
# options (like visibility, nullability, validation) and consolidates them
|
10
|
+
# into a consistent internal representation.
|
11
|
+
#
|
12
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
13
|
+
# @since 0.1.0
|
14
|
+
class OptionParser
|
15
|
+
type options = { ?callbacks: Array[Attribute::Callback::handler] | Attribute::Callback::handler, ?callback: Array[Attribute::Callback::handler] | Attribute::Callback::handler, ?coerce: Array[Attribute::Coercer::handler] | Attribute::Coercer::handler, ?coercers: Array[Attribute::Coercer::handler], ?coerce_with: [ Attribute::Coercer::handler ] | Attribute::Coercer::handler, ?default: untyped, ?default_generator: untyped, ?default_value: untyped, ?desc: String?, ?description: String, ?non_nil: bool, ?non_null: bool, ?non_nullable: bool, ?not_nil: bool, ?not_nilable: bool, ?not_null: bool, ?not_nullable: bool, ?null: bool, ?on_change: Array[Attribute::Callback::handler] | Attribute::Callback::handler, ?optional: bool, ?position: Integer?, ?read: Attribute::Signature::visibility_symbol, ?read_access: Attribute::Signature::visibility_symbol, ?reader: Attribute::Signature::visibility_symbol, ?required: bool, ?validate: Array[Attribute::Validator::handler] | Attribute::Validator::handler, ?validate_with: Array[Attribute::Validator::handler] | Attribute::Validator::handler, ?validators: Array[Attribute::Validator::handler] | Attribute::Validator::handler, ?write_access: Attribute::Signature::visibility_symbol, ?writer: Attribute::Signature::visibility_symbol } & Hash[Symbol, untyped]
|
16
|
+
|
17
|
+
type result = { callbacks: Array[Attribute::Callback::handler], coercers: Array[Attribute::Coercer::handler], ?default: untyped, ?description: String, name: Symbol, ?nilable: bool, ?position: Integer?, ?required: bool, ?read: Attribute::Signature::visibility_symbol, type: Attribute::Signature::type_symbol, validators: Array[Attribute::Validator::handler], ?write: Attribute::Signature::visibility_symbol }
|
18
|
+
|
19
|
+
# Alternative keys for reader visibility settings
|
20
|
+
ACCESSOR_READER_KEYS: Array[Symbol]
|
21
|
+
|
22
|
+
# Alternative keys for writer visibility settings
|
23
|
+
ACCESSOR_WRITER_KEYS: Array[Symbol]
|
24
|
+
|
25
|
+
# Alternative keys for change callbacks
|
26
|
+
CALLBACK_KEYS: Array[Symbol]
|
27
|
+
|
28
|
+
# Alternative keys for coercion handlers
|
29
|
+
COERCER_KEYS: Array[Symbol]
|
30
|
+
|
31
|
+
# Alternative keys for default value settings
|
32
|
+
DEFAULT_KEYS: Array[Symbol]
|
33
|
+
|
34
|
+
# Alternative keys for description
|
35
|
+
DESCRIPTION_KEYS: Array[Symbol]
|
36
|
+
|
37
|
+
# Pattern for matching nilability-related keys
|
38
|
+
NILABLE_PATTERN: Regexp
|
39
|
+
|
40
|
+
# Keys that indicate non-nilable requirement
|
41
|
+
NON_NILABLE_KEYS: Array[Symbol]
|
42
|
+
|
43
|
+
# Alternative keys for validators
|
44
|
+
VALIDATOR_KEYS: Array[Symbol]
|
45
|
+
|
46
|
+
@result: result
|
47
|
+
|
48
|
+
@options: options
|
49
|
+
|
50
|
+
# Parse attribute options into a normalized format.
|
51
|
+
#
|
52
|
+
# @param attribute_name [String, Symbol] the name of the attribute
|
53
|
+
# @param attribute_type [String, Symbol] the type of attribute
|
54
|
+
# @param options [Hash] the options to parse
|
55
|
+
#
|
56
|
+
# @return [Hash] normalized options suitable for attribute creation
|
57
|
+
def self.parse!: (String | Symbol attribute_name, String | Symbol attribute_type, options options) -> void
|
58
|
+
|
59
|
+
# Initialize a new OptionParser.
|
60
|
+
#
|
61
|
+
# @param attribute_name [String, Symbol] the name of the attribute
|
62
|
+
# @param attribute_type [String, Symbol] the type of attribute
|
63
|
+
# @param options [Hash] the options to parse
|
64
|
+
#
|
65
|
+
# @return [void]
|
66
|
+
def initialize: (String | Symbol attribute_name, String | Symbol attribute_type, options options) -> void
|
67
|
+
|
68
|
+
# Parse the options into a normalized format.
|
69
|
+
#
|
70
|
+
# @return [Hash] normalized options suitable for attribute creation
|
71
|
+
def parse!: () -> result
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
# Find the last set value among multiple option keys.
|
76
|
+
#
|
77
|
+
# @param keys [Array<Symbol>] the keys to check
|
78
|
+
#
|
79
|
+
# @return [Object] the last set value or Undefined
|
80
|
+
def find_last_option: (Array[Symbol]) -> untyped
|
81
|
+
|
82
|
+
# Parse accessor (reader/writer) visibility options.
|
83
|
+
#
|
84
|
+
# @return [void]
|
85
|
+
def parse_accessor_options!: () -> void
|
86
|
+
|
87
|
+
# Parse callback handler options.
|
88
|
+
#
|
89
|
+
# @return [void]
|
90
|
+
def parse_callbacks_options!: () -> void
|
91
|
+
|
92
|
+
# Parse coercion handler options.
|
93
|
+
#
|
94
|
+
# @return [void]
|
95
|
+
def parse_coercers_options!: () -> void
|
96
|
+
|
97
|
+
# Parse default value options.
|
98
|
+
#
|
99
|
+
# @return [void]
|
100
|
+
def parse_default_options!: () -> void
|
101
|
+
|
102
|
+
# Parse description options.
|
103
|
+
#
|
104
|
+
# @return [void]
|
105
|
+
def parse_description_options!: () -> void
|
106
|
+
|
107
|
+
# Parse nilability options.
|
108
|
+
#
|
109
|
+
# @return [void]
|
110
|
+
def parse_nilable_options!: () -> void
|
111
|
+
|
112
|
+
# Parse all option types.
|
113
|
+
#
|
114
|
+
# @return [void]
|
115
|
+
def parse_options!: () -> void
|
116
|
+
|
117
|
+
# Parse required/optional options.
|
118
|
+
#
|
119
|
+
# @return [void]
|
120
|
+
def parse_required_options!: () -> void
|
121
|
+
|
122
|
+
# Parse validator options.
|
123
|
+
#
|
124
|
+
# @return [void]
|
125
|
+
def parse_validator_options!: () -> void
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
module Domainic
|
2
|
+
module Attributer
|
3
|
+
module DSL
|
4
|
+
# A class responsible for configuring attributes through a fluent interface.
|
5
|
+
#
|
6
|
+
# This class provides a rich DSL for configuring attributes with support for
|
7
|
+
# default values, coercion, validation, visibility controls, and change tracking.
|
8
|
+
# It uses method chaining to allow natural, declarative attribute definitions.
|
9
|
+
#
|
10
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
11
|
+
# @since 0.1.0
|
12
|
+
class AttributeBuilder
|
13
|
+
@base: __todo__
|
14
|
+
|
15
|
+
@options: OptionParser::result
|
16
|
+
|
17
|
+
# Initialize a new AttributeBuilder.
|
18
|
+
#
|
19
|
+
# @param base [Class, Module] the class or module to build the attribute in
|
20
|
+
# @param attribute_name [String, Symbol] the name of the attribute
|
21
|
+
# @param attribute_type [String, Symbol] the type of attribute
|
22
|
+
# @param type_validator [Proc, Object, nil] optional type validator
|
23
|
+
# @param options [Hash] additional options for attribute configuration
|
24
|
+
# @yield configuration block for additional attribute settings
|
25
|
+
#
|
26
|
+
# @return [void]
|
27
|
+
def initialize: (__todo__ base, String | Symbol attribute_name, String | Symbol attribute_type, ?Attribute::Validator::handler? type_validator, OptionParser::options options) ?{ (?) [self: AttributeBuilder] -> void } -> void
|
28
|
+
|
29
|
+
# Builds and finalizes the attribute.
|
30
|
+
#
|
31
|
+
# @return [Attribute] the configured attribute
|
32
|
+
def build!: () -> Attribute
|
33
|
+
|
34
|
+
# Configure value coercion.
|
35
|
+
#
|
36
|
+
# @param proc_symbol [Proc, Symbol, nil] optional coercion handler
|
37
|
+
# @yield optional coercion block
|
38
|
+
#
|
39
|
+
# @return [self] the builder for method chaining
|
40
|
+
def coerce_with: (?(Attribute::Coercer::proc | Object)? proc_symbol) ?{ (untyped value) -> untyped } -> self
|
41
|
+
|
42
|
+
alias coerce coerce_with
|
43
|
+
|
44
|
+
# Configure default value.
|
45
|
+
#
|
46
|
+
# @param value_or_proc [Object, Proc, nil] optional default value or generator
|
47
|
+
# @yield optional default value generator block
|
48
|
+
#
|
49
|
+
# @return [self] the builder for method chaining
|
50
|
+
def default: (?untyped? value_or_proc) ?{ (?) -> untyped } -> self
|
51
|
+
|
52
|
+
alias default_generator default
|
53
|
+
|
54
|
+
alias default_value default
|
55
|
+
|
56
|
+
# Set attribute description.
|
57
|
+
#
|
58
|
+
# @param text [String] the description text
|
59
|
+
#
|
60
|
+
# @return [self] the builder for method chaining
|
61
|
+
def description: (String? text) -> self
|
62
|
+
|
63
|
+
alias desc description
|
64
|
+
|
65
|
+
# Mark attribute as non-nilable.
|
66
|
+
#
|
67
|
+
# @return [self] the builder for method chaining
|
68
|
+
def non_nilable: () -> self
|
69
|
+
|
70
|
+
alias non_nil non_nilable
|
71
|
+
|
72
|
+
alias non_null non_nilable
|
73
|
+
|
74
|
+
alias non_nullable non_nilable
|
75
|
+
|
76
|
+
alias not_nil non_nilable
|
77
|
+
|
78
|
+
alias not_nilable non_nilable
|
79
|
+
|
80
|
+
alias not_null non_nilable
|
81
|
+
|
82
|
+
alias not_nullable non_nilable
|
83
|
+
|
84
|
+
# Configure change callback.
|
85
|
+
#
|
86
|
+
# @param proc [Proc, nil] optional callback handler
|
87
|
+
# @yield optional callback block
|
88
|
+
#
|
89
|
+
# @return [self] the builder for method chaining
|
90
|
+
def on_change: (?Attribute::Callback::handler? proc) ?{ (untyped old_value, untyped new_value) -> void } -> self
|
91
|
+
|
92
|
+
# Set private visibility for both read and write.
|
93
|
+
#
|
94
|
+
# @return [self] the builder for method chaining
|
95
|
+
def private: () -> self
|
96
|
+
|
97
|
+
# Set private visibility for read.
|
98
|
+
#
|
99
|
+
# @return [self] the builder for method chaining
|
100
|
+
def private_read: () -> self
|
101
|
+
|
102
|
+
# Set private visibility for write.
|
103
|
+
#
|
104
|
+
# @return [self] the builder for method chaining
|
105
|
+
def private_write: () -> self
|
106
|
+
|
107
|
+
# Set protected visibility for both read and write.
|
108
|
+
#
|
109
|
+
# @return [self] the builder for method chaining
|
110
|
+
def protected: () -> self
|
111
|
+
|
112
|
+
# Set protected visibility for read.
|
113
|
+
#
|
114
|
+
# @return [self] the builder for method chaining
|
115
|
+
def protected_read: () -> self
|
116
|
+
|
117
|
+
# Set protected visibility for write.
|
118
|
+
#
|
119
|
+
# @return [self] the builder for method chaining
|
120
|
+
def protected_write: () -> self
|
121
|
+
|
122
|
+
# Set public visibility for both read and write.
|
123
|
+
#
|
124
|
+
# @return [self] the builder for method chaining
|
125
|
+
def public: () -> self
|
126
|
+
|
127
|
+
# Set public visibility for read.
|
128
|
+
#
|
129
|
+
# @return [self] the builder for method chaining
|
130
|
+
def public_read: () -> self
|
131
|
+
|
132
|
+
# Set public visibility for write.
|
133
|
+
#
|
134
|
+
# @return [self] the builder for method chaining
|
135
|
+
def public_write: () -> self
|
136
|
+
|
137
|
+
# Mark attribute as required.
|
138
|
+
#
|
139
|
+
# @return [self] the builder for method chaining
|
140
|
+
def required: () -> self
|
141
|
+
|
142
|
+
# Configure value validation.
|
143
|
+
#
|
144
|
+
# @param object_or_proc [Object, Proc, nil] optional validation handler
|
145
|
+
# @yield optional validation block
|
146
|
+
#
|
147
|
+
# @return [self] the builder for method chaining
|
148
|
+
def validate_with: (?Attribute::Validator::handler? object_or_proc) ?{ (untyped value) -> boolish } -> self
|
149
|
+
|
150
|
+
alias validate validate_with
|
151
|
+
|
152
|
+
alias validates validate_with
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Domainic
|
2
|
+
module Attributer
|
3
|
+
module DSL
|
4
|
+
# A class responsible for handling object initialization with attributes.
|
5
|
+
#
|
6
|
+
# This class manages the process of setting attribute values during object
|
7
|
+
# initialization. It handles both positional arguments and keyword options,
|
8
|
+
# applying them to their corresponding attributes while respecting default
|
9
|
+
# values and required attributes.
|
10
|
+
#
|
11
|
+
# @author {https://aaronmallen.me Aaron Allen}
|
12
|
+
# @since 0.1.0
|
13
|
+
class Initializer
|
14
|
+
@argument_attributes: Array[Attribute]
|
15
|
+
|
16
|
+
@option_attributes: Array[Attribute]
|
17
|
+
|
18
|
+
@base: Object
|
19
|
+
|
20
|
+
@attributes: AttributeSet
|
21
|
+
|
22
|
+
# Initialize a new Initializer.
|
23
|
+
#
|
24
|
+
# @param base [Object] the instance being initialized
|
25
|
+
#
|
26
|
+
# @return [void]
|
27
|
+
def initialize: (Object base) -> void
|
28
|
+
|
29
|
+
# Assign values to attributes.
|
30
|
+
#
|
31
|
+
# Validates and applies both positional arguments and keyword options to
|
32
|
+
# their corresponding attributes. Raises an error if required arguments
|
33
|
+
# are missing.
|
34
|
+
#
|
35
|
+
# @param arguments [Array] positional arguments to assign
|
36
|
+
# @param keyword_arguments [Hash] keyword arguments to assign
|
37
|
+
#
|
38
|
+
# @raise [ArgumentError] if required arguments are missing
|
39
|
+
# @return [void]
|
40
|
+
def assign!: (*untyped arguments, **untyped keyword_arguments) -> void
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
# Access to the current attribute set.
|
45
|
+
#
|
46
|
+
# @return [AttributeSet] the attribute set for this instance
|
47
|
+
attr_reader attributes: AttributeSet
|
48
|
+
|
49
|
+
# Apply positional arguments to their attributes.
|
50
|
+
#
|
51
|
+
# @param arguments [Array] the positional arguments to apply
|
52
|
+
#
|
53
|
+
# @return [void]
|
54
|
+
def apply_arguments: (Array[untyped]) -> void
|
55
|
+
|
56
|
+
# Apply keyword arguments to their attributes.
|
57
|
+
#
|
58
|
+
# @param options [Hash] the keyword options to apply
|
59
|
+
#
|
60
|
+
# @return [void]
|
61
|
+
def apply_options!: (Hash[String | Symbol, untyped]) -> void
|
62
|
+
|
63
|
+
# Get all argument attributes.
|
64
|
+
#
|
65
|
+
# @return [Array<Attribute>] the argument attributes
|
66
|
+
def argument_attributes: () -> Array[Attribute]
|
67
|
+
|
68
|
+
# Assign a value to an attribute.
|
69
|
+
#
|
70
|
+
# @param attribute_name [Symbol] the name of the attribute
|
71
|
+
# @param value [Object] the value to assign
|
72
|
+
#
|
73
|
+
# @return [void]
|
74
|
+
def assign_value: (untyped attribute_name, untyped value) -> untyped
|
75
|
+
|
76
|
+
# Get all option attributes.
|
77
|
+
#
|
78
|
+
# @return [Array<Attribute>] the option attributes
|
79
|
+
def option_attributes: () -> Array[Attribute]
|
80
|
+
|
81
|
+
# Validate that all required positional arguments are provided.
|
82
|
+
#
|
83
|
+
# @param arguments [Array] the arguments to validate
|
84
|
+
#
|
85
|
+
# @raise [ArgumentError] if required arguments are missing
|
86
|
+
# @return [void]
|
87
|
+
def validate_positional_arguments!: (Array[untyped]) -> void
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|