domainic-attributer 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|