domainic-attributer 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +11 -0
- data/CHANGELOG.md +32 -1
- data/README.md +42 -355
- data/docs/USAGE.md +723 -0
- data/lib/domainic/attributer/attribute/callback.rb +21 -9
- data/lib/domainic/attributer/attribute/coercer.rb +28 -13
- data/lib/domainic/attributer/attribute/mixin/belongs_to_attribute.rb +16 -13
- data/lib/domainic/attributer/attribute/signature.rb +43 -32
- data/lib/domainic/attributer/attribute/validator.rb +46 -16
- data/lib/domainic/attributer/attribute.rb +28 -18
- data/lib/domainic/attributer/attribute_set.rb +21 -19
- data/lib/domainic/attributer/class_methods.rb +136 -83
- data/lib/domainic/attributer/dsl/attribute_builder/option_parser.rb +64 -22
- data/lib/domainic/attributer/dsl/attribute_builder.rb +515 -26
- data/lib/domainic/attributer/dsl/initializer.rb +23 -18
- data/lib/domainic/attributer/dsl/method_injector.rb +16 -14
- data/lib/domainic/attributer/errors/aggregate_error.rb +36 -0
- data/lib/domainic/attributer/errors/callback_execution_error.rb +30 -0
- data/lib/domainic/attributer/errors/coercion_execution_error.rb +37 -0
- data/lib/domainic/attributer/errors/error.rb +19 -0
- data/lib/domainic/attributer/errors/validation_execution_error.rb +30 -0
- data/lib/domainic/attributer/instance_methods.rb +11 -8
- data/lib/domainic/attributer/undefined.rb +9 -7
- data/lib/domainic/attributer.rb +88 -27
- data/sig/domainic/attributer/attribute/callback.rbs +10 -7
- data/sig/domainic/attributer/attribute/coercer.rbs +14 -11
- data/sig/domainic/attributer/attribute/mixin/belongs_to_attribute.rbs +14 -12
- data/sig/domainic/attributer/attribute/signature.rbs +43 -32
- data/sig/domainic/attributer/attribute/validator.rbs +28 -13
- data/sig/domainic/attributer/attribute.rbs +27 -17
- data/sig/domainic/attributer/attribute_set.rbs +21 -19
- data/sig/domainic/attributer/class_methods.rbs +133 -80
- data/sig/domainic/attributer/dsl/attribute_builder/option_parser.rbs +62 -22
- data/sig/domainic/attributer/dsl/attribute_builder.rbs +515 -26
- data/sig/domainic/attributer/dsl/initializer.rbs +21 -19
- data/sig/domainic/attributer/dsl/method_injector.rbs +16 -14
- data/sig/domainic/attributer/errors/aggregate_error.rbs +28 -0
- data/sig/domainic/attributer/errors/callback_execution_error.rbs +23 -0
- data/sig/domainic/attributer/errors/coercion_execution_error.rbs +29 -0
- data/sig/domainic/attributer/errors/error.rbs +17 -0
- data/sig/domainic/attributer/errors/validation_execution_error.rbs +23 -0
- data/sig/domainic/attributer/instance_methods.rbs +11 -8
- data/sig/domainic/attributer/undefined.rbs +5 -3
- data/sig/domainic/attributer.rbs +88 -27
- metadata +19 -6
@@ -8,13 +8,15 @@ require 'domainic/attributer/undefined'
|
|
8
8
|
|
9
9
|
module Domainic
|
10
10
|
module Attributer
|
11
|
-
# A class representing a managed attribute in the Domainic::Attributer system
|
11
|
+
# A class representing a managed attribute in the {Domainic::Attributer} system
|
12
12
|
#
|
13
13
|
# This class serves as the core component of the attribute management system.
|
14
14
|
# It coordinates type information, visibility settings, value coercion,
|
15
15
|
# validation, and change notifications for an attribute. Each instance
|
16
|
-
# represents a single attribute definition within a class
|
16
|
+
# represents a single attribute definition within a class
|
17
17
|
#
|
18
|
+
# @api private
|
19
|
+
# @!visibility private
|
18
20
|
# @author {https://aaronmallen.me Aaron Allen}
|
19
21
|
# @since 0.1.0
|
20
22
|
class Attribute
|
@@ -43,22 +45,30 @@ module Domainic
|
|
43
45
|
# @rbs @signature: Signature
|
44
46
|
# @rbs @validator: Validator
|
45
47
|
|
48
|
+
# Get the class or module this attribute belongs to
|
49
|
+
#
|
46
50
|
# @return [Class, Module] the class or module this attribute belongs to
|
47
51
|
attr_reader :base #: __todo__
|
48
52
|
|
53
|
+
# Get the description of the attribute
|
54
|
+
#
|
49
55
|
# @return [String, nil] the description of the attribute
|
50
56
|
attr_reader :description #: String?
|
51
57
|
|
58
|
+
# Get the name of the attribute
|
59
|
+
#
|
52
60
|
# @return [Symbol] the name of the attribute
|
53
61
|
attr_reader :name #: Symbol
|
54
62
|
|
63
|
+
# Get the signature configuration for this attribute
|
64
|
+
#
|
55
65
|
# @return [Signature] the signature configuration for this attribute
|
56
66
|
attr_reader :signature #: Signature
|
57
67
|
|
58
|
-
# Initialize a new Attribute instance
|
68
|
+
# Initialize a new {Attribute} instance
|
59
69
|
#
|
60
70
|
# @param base [Class, Module] the class or module this attribute belongs to
|
61
|
-
# @param options [Hash] the options to create the attribute with
|
71
|
+
# @param options [Hash{Symbol => Object}] the options to create the attribute with
|
62
72
|
# @option options [Array<Proc>, Proc] :callbacks callbacks to trigger on value changes
|
63
73
|
# @option options [Array<Proc, Symbol>, Proc, Symbol] :coercers handlers for value coercion
|
64
74
|
# @option options [Object] :default the default value or generator
|
@@ -73,8 +83,7 @@ module Domainic
|
|
73
83
|
# @option options [Symbol] :write the write visibility
|
74
84
|
#
|
75
85
|
# @raise [ArgumentError] if the configuration is invalid
|
76
|
-
# @return [
|
77
|
-
#
|
86
|
+
# @return [Attribute] the new Attribute instance
|
78
87
|
# @rbs (
|
79
88
|
# __todo__ base,
|
80
89
|
# ?callbacks: Array[Callback::handler] | Callback::handler,
|
@@ -98,7 +107,7 @@ module Domainic
|
|
98
107
|
raise ArgumentError, e.message
|
99
108
|
end
|
100
109
|
|
101
|
-
# Apply a value to the attribute on an instance
|
110
|
+
# Apply a value to the attribute on an instance
|
102
111
|
#
|
103
112
|
# This method applies all attribute constraints (coercion, validation) to a value
|
104
113
|
# and sets it on the given instance. It manages the complete lifecycle of setting
|
@@ -119,7 +128,7 @@ module Domainic
|
|
119
128
|
old_value = instance.instance_variable_get(:"@#{name}")
|
120
129
|
|
121
130
|
coerced_value = value == Undefined ? generate_default(instance) : value
|
122
|
-
coerced_value = @coercer.call(instance, coerced_value)
|
131
|
+
coerced_value = @coercer.call(instance, coerced_value)
|
123
132
|
|
124
133
|
@validator.call(instance, coerced_value)
|
125
134
|
|
@@ -128,7 +137,7 @@ module Domainic
|
|
128
137
|
@callback.call(instance, old_value, coerced_value)
|
129
138
|
end
|
130
139
|
|
131
|
-
# Check if this attribute has a default value
|
140
|
+
# Check if this attribute has a default value
|
132
141
|
#
|
133
142
|
# @return [Boolean] true if a default value is set
|
134
143
|
# @rbs () -> bool
|
@@ -136,10 +145,11 @@ module Domainic
|
|
136
145
|
@default != Undefined
|
137
146
|
end
|
138
147
|
|
139
|
-
# Create a duplicate instance for a new base class
|
148
|
+
# Create a duplicate instance for a new base class
|
140
149
|
#
|
141
150
|
# @param new_base [Class, Module] the new base class
|
142
151
|
#
|
152
|
+
# @raise [ArgumentError] if the new base is invalid
|
143
153
|
# @return [Attribute] the duplicated instance
|
144
154
|
# @rbs (__todo__ new_base) -> Attribute
|
145
155
|
def dup_with_base(new_base)
|
@@ -148,7 +158,7 @@ module Domainic
|
|
148
158
|
dup.tap { |duped| duped.instance_variable_set(:@base, new_base) }
|
149
159
|
end
|
150
160
|
|
151
|
-
# Generate the default value for this attribute
|
161
|
+
# Generate the default value for this attribute
|
152
162
|
#
|
153
163
|
# @param instance [Object] the instance to generate the default for
|
154
164
|
#
|
@@ -158,11 +168,11 @@ module Domainic
|
|
158
168
|
@default.is_a?(Proc) ? instance.instance_exec(&@default) : @default
|
159
169
|
end
|
160
170
|
|
161
|
-
# Merge this attribute's configuration with another
|
171
|
+
# Merge this attribute's configuration with another
|
162
172
|
#
|
163
173
|
# @param other [Attribute] the attribute to merge with
|
164
174
|
#
|
165
|
-
# @raise [ArgumentError] if other is not an Attribute
|
175
|
+
# @raise [ArgumentError] if other is not an {Attribute}
|
166
176
|
# @return [Attribute] a new attribute with merged configuration
|
167
177
|
# @rbs (Attribute other) -> Attribute
|
168
178
|
def merge(other)
|
@@ -173,7 +183,7 @@ module Domainic
|
|
173
183
|
|
174
184
|
private
|
175
185
|
|
176
|
-
# Apply initialization options to create attribute components
|
186
|
+
# Apply initialization options to create attribute components
|
177
187
|
#
|
178
188
|
# @param base [Class, Module] the base class
|
179
189
|
# @param options [Hash] the initialization options
|
@@ -193,7 +203,7 @@ module Domainic
|
|
193
203
|
@validator = Validator.new(self, options.fetch(:validators, []))
|
194
204
|
end
|
195
205
|
|
196
|
-
# Initialize a copy of this attribute
|
206
|
+
# Initialize a copy of this attribute
|
197
207
|
#
|
198
208
|
# @param source [Attribute] the source attribute
|
199
209
|
#
|
@@ -211,7 +221,7 @@ module Domainic
|
|
211
221
|
super
|
212
222
|
end
|
213
223
|
|
214
|
-
# Get this attribute's configuration as options
|
224
|
+
# Get this attribute's configuration as options
|
215
225
|
#
|
216
226
|
# @return [Hash] the configuration options
|
217
227
|
# @rbs () -> initialize_options
|
@@ -226,7 +236,7 @@ module Domainic
|
|
226
236
|
}.merge(signature.send(:to_options)) #: initialize_options
|
227
237
|
end
|
228
238
|
|
229
|
-
# Validate and apply initialization options
|
239
|
+
# Validate and apply initialization options
|
230
240
|
#
|
231
241
|
# @param base [Class, Module] the base class
|
232
242
|
# @param options [Hash] the initialization options
|
@@ -238,7 +248,7 @@ module Domainic
|
|
238
248
|
apply_initialize_options!(base, options)
|
239
249
|
end
|
240
250
|
|
241
|
-
# Validate initialization options
|
251
|
+
# Validate initialization options
|
242
252
|
#
|
243
253
|
# @param base [Class, Module] the base class
|
244
254
|
# @param options [Hash] the initialization options
|
@@ -5,14 +5,16 @@ require 'forwardable'
|
|
5
5
|
|
6
6
|
module Domainic
|
7
7
|
module Attributer
|
8
|
-
# A class
|
8
|
+
# A class responsible for managing an ordered collection of attributes
|
9
9
|
#
|
10
10
|
# This class manages a set of attributes for a given class or module. It maintains
|
11
11
|
# attributes in a specific order determined by their type (argument vs option),
|
12
12
|
# default values, and position. The collection supports standard operations like
|
13
13
|
# adding, selecting, and merging attributes while maintaining proper ownership
|
14
|
-
# relationships with their base class
|
14
|
+
# relationships with their base class
|
15
15
|
#
|
16
|
+
# @api private
|
17
|
+
# @!visibility private
|
16
18
|
# @author {https://aaronmallen.me Aaron Allen}
|
17
19
|
# @since 0.1.0
|
18
20
|
class AttributeSet
|
@@ -21,12 +23,12 @@ module Domainic
|
|
21
23
|
# @rbs @base: __todo__
|
22
24
|
# @rbs @lookup: Hash[Symbol, Attribute]
|
23
25
|
|
24
|
-
# Initialize a new AttributeSet
|
26
|
+
# Initialize a new AttributeSet
|
25
27
|
#
|
26
28
|
# @param base [Class, Module] the class or module this set belongs to
|
27
29
|
# @param attributes [Array<Attribute>] initial attributes to add
|
28
30
|
#
|
29
|
-
# @return [
|
31
|
+
# @return [AttributeSet] the new AttributeSet instance
|
30
32
|
# @rbs (__todo__ base, ?Array[Attribute] attributes) -> void
|
31
33
|
def initialize(base, attributes = [])
|
32
34
|
@base = base
|
@@ -34,7 +36,7 @@ module Domainic
|
|
34
36
|
attributes.each { |attribute| add(attribute) }
|
35
37
|
end
|
36
38
|
|
37
|
-
# Get an attribute by name
|
39
|
+
# Get an attribute by name
|
38
40
|
#
|
39
41
|
# @param attribute_name [String, Symbol] the name of the attribute
|
40
42
|
#
|
@@ -44,16 +46,16 @@ module Domainic
|
|
44
46
|
@lookup[attribute_name.to_sym]
|
45
47
|
end
|
46
48
|
|
47
|
-
# Add an attribute to the set
|
49
|
+
# Add an attribute to the set
|
48
50
|
#
|
49
51
|
# If an attribute with the same name exists, the attributes are merged.
|
50
52
|
# If the attribute belongs to a different base class, it is duplicated
|
51
53
|
# with the correct base. After adding, attributes are sorted by type
|
52
|
-
# and position
|
54
|
+
# and position
|
53
55
|
#
|
54
56
|
# @param attribute [Attribute] the attribute to add
|
55
57
|
#
|
56
|
-
# @raise [ArgumentError] if attribute is
|
58
|
+
# @raise [ArgumentError] if attribute is not a valid {Attribute}
|
57
59
|
# @return [void]
|
58
60
|
# @rbs (Attribute attribute) -> void
|
59
61
|
def add(attribute)
|
@@ -71,7 +73,7 @@ module Domainic
|
|
71
73
|
nil
|
72
74
|
end
|
73
75
|
|
74
|
-
# Check if an attribute exists in the set
|
76
|
+
# Check if an attribute exists in the set
|
75
77
|
#
|
76
78
|
# @param attribute_name [String, Symbol] the name to check
|
77
79
|
#
|
@@ -80,7 +82,7 @@ module Domainic
|
|
80
82
|
@lookup.key?(attribute_name.to_sym)
|
81
83
|
end
|
82
84
|
|
83
|
-
# Get all attribute names
|
85
|
+
# Get all attribute names
|
84
86
|
#
|
85
87
|
# @return [Array<Symbol>] the attribute names
|
86
88
|
# @rbs () -> Array[Symbol]
|
@@ -88,7 +90,7 @@ module Domainic
|
|
88
90
|
@lookup.keys
|
89
91
|
end
|
90
92
|
|
91
|
-
# Get all attributes
|
93
|
+
# Get all attributes
|
92
94
|
#
|
93
95
|
# @return [Array<Attribute>] the attributes
|
94
96
|
# @rbs () -> Array[Attribute]
|
@@ -99,7 +101,7 @@ module Domainic
|
|
99
101
|
# @rbs! def count: () ?{ (Symbol, Attribute) -> boolish } -> Integer
|
100
102
|
def_delegators :@lookup, :count
|
101
103
|
|
102
|
-
# Create a duplicate set for a new base class
|
104
|
+
# Create a duplicate set for a new base class
|
103
105
|
#
|
104
106
|
# @param new_base [Class, Module] the new base class
|
105
107
|
#
|
@@ -115,7 +117,7 @@ module Domainic
|
|
115
117
|
end
|
116
118
|
end
|
117
119
|
|
118
|
-
# Iterate over attribute name/value pairs
|
120
|
+
# Iterate over attribute name/value pairs
|
119
121
|
#
|
120
122
|
# @yield [name, attribute] each name/attribute pair
|
121
123
|
# @yieldparam name [Symbol] the attribute name
|
@@ -132,7 +134,7 @@ module Domainic
|
|
132
134
|
# @rbs! def empty?: () -> bool
|
133
135
|
def_delegators :@lookup, :empty?
|
134
136
|
|
135
|
-
# Create a new set excluding specified attributes
|
137
|
+
# Create a new set excluding specified attributes
|
136
138
|
#
|
137
139
|
# @param attribute_names [Array<String, Symbol>] names to exclude
|
138
140
|
#
|
@@ -145,7 +147,7 @@ module Domainic
|
|
145
147
|
# @rbs! def length: () -> Integer
|
146
148
|
def_delegators :@lookup, :length
|
147
149
|
|
148
|
-
# Merge another set into this one
|
150
|
+
# Merge another set into this one
|
149
151
|
#
|
150
152
|
# @param other [AttributeSet] the set to merge
|
151
153
|
#
|
@@ -155,7 +157,7 @@ module Domainic
|
|
155
157
|
self.class.new(other.instance_variable_get(:@base), attributes + other.attributes)
|
156
158
|
end
|
157
159
|
|
158
|
-
# Create a new set with rejected attributes
|
160
|
+
# Create a new set with rejected attributes
|
159
161
|
#
|
160
162
|
# @yield [name, attribute] each name/attribute pair
|
161
163
|
# @yieldparam name [Symbol] the attribute name
|
@@ -167,7 +169,7 @@ module Domainic
|
|
167
169
|
self.class.new(@base, @lookup.reject(...).values)
|
168
170
|
end
|
169
171
|
|
170
|
-
# Create a new set with selected attributes
|
172
|
+
# Create a new set with selected attributes
|
171
173
|
#
|
172
174
|
# @yield [name, attribute] each name/attribute pair
|
173
175
|
# @yieldparam name [Symbol] the attribute name
|
@@ -184,10 +186,10 @@ module Domainic
|
|
184
186
|
|
185
187
|
private
|
186
188
|
|
187
|
-
# Sort attributes by type and position
|
189
|
+
# Sort attributes by type and position
|
188
190
|
#
|
189
191
|
# Attributes are sorted first by type (required arguments, defaulted arguments,
|
190
|
-
# then options), and then by their position within those groups
|
192
|
+
# then options), and then by their position within those groups
|
191
193
|
#
|
192
194
|
# @return [void]
|
193
195
|
# @rbs () -> void
|
@@ -7,81 +7,110 @@ require 'domainic/attributer/undefined'
|
|
7
7
|
|
8
8
|
module Domainic
|
9
9
|
module Attributer
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# This module extends classes that include Domainic::Attributer with methods for
|
13
|
-
# defining and managing attributes. It supports two types of attributes:
|
10
|
+
# This module extends classes that include {Domainic::Attributer} with methods for defining and managing attributes.
|
11
|
+
# It supports two types of attributes:
|
14
12
|
# 1. Arguments - Positional parameters that must be provided in a specific order
|
15
13
|
# 2. Options - Named parameters that can be provided in any order
|
16
14
|
#
|
15
|
+
# @note This module is automatically extended when {Domainic::Attributer} is included in a class
|
16
|
+
#
|
17
17
|
# @example Defining arguments and options
|
18
18
|
# class Person
|
19
19
|
# include Domainic::Attributer
|
20
20
|
#
|
21
|
-
# argument :name,
|
22
|
-
# argument :age do
|
23
|
-
#
|
21
|
+
# argument :name, String
|
22
|
+
# argument :age, Integer do
|
23
|
+
# validate_with ->(val) { val >= 0 }
|
24
24
|
# end
|
25
25
|
#
|
26
|
-
# option :email,
|
27
|
-
# option :role do
|
28
|
-
# %w[admin user guest].include?(
|
26
|
+
# option :email, String, default: nil
|
27
|
+
# option :role do
|
28
|
+
# validate_with ->(val) { %w[admin user guest].include?(val) }
|
29
29
|
# end
|
30
30
|
# end
|
31
31
|
#
|
32
|
+
# person = Person.new('Alice', 30, email: 'alice123@gmail.com', role: 'user')
|
33
|
+
# # => #<Person:0x0000000104bc5f98 @age=30, @email="alice123@gmail.com", @name="Alice", @role="user">
|
34
|
+
#
|
32
35
|
# @author {https://aaronmallen.me Aaron Allen}
|
33
36
|
# @since 0.1.0
|
34
37
|
module ClassMethods
|
35
38
|
# @rbs @__attributes__: AttributeSet
|
36
39
|
|
37
|
-
# Define a positional argument attribute
|
38
|
-
#
|
39
|
-
# Arguments are required by default and must be provided in the order they are defined
|
40
|
-
# They can be type-validated and configured with additional options like defaults
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
# @
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
68
|
-
# @
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
# :
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
# :
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
84
|
-
#
|
40
|
+
# Define a positional argument attribute
|
41
|
+
#
|
42
|
+
# Arguments are required by default and must be provided in the order they are defined unless they have a default
|
43
|
+
# value. They can be type-validated and configured with additional options like defaults and visibility
|
44
|
+
#
|
45
|
+
# @see DSL::AttributeBuilder
|
46
|
+
#
|
47
|
+
# @example Using the options API
|
48
|
+
# class Person
|
49
|
+
# argument :name, String
|
50
|
+
# argument :age, ->(val) { val.is_a?(Integer) && val >= 0 }
|
51
|
+
# argument :role, default: 'user'
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# @example Using the block API
|
55
|
+
# class Person
|
56
|
+
# argument :name, String do
|
57
|
+
# validate_with ->(val) { val.length >= 3 }
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# argument :age, Integer do
|
61
|
+
# coerce_with ->(val) { val.to_i }
|
62
|
+
# validate_with ->(val) { val >= 0 }
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# argument :role, String do
|
66
|
+
# validate_with ->(val) { VALID_USER_ROLES.include?(val) }
|
67
|
+
# default 'user'
|
68
|
+
# end
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# @overload argument(attribute_name, type_validator = nil, **options)
|
72
|
+
# @param attribute_name [String, Symbol] the name of the attribute
|
73
|
+
# @param type_validator [Proc, Object, nil] optional validation handler for type checking
|
74
|
+
# @param options [Hash{Symbol => Object}] additional configuration options
|
75
|
+
# @option options [Array<Proc>, Proc] :callbacks handlers for attribute change events (priority over
|
76
|
+
# :callback, :on_change)
|
77
|
+
# @option options [Array<Proc>, Proc] :callback alias for :callbacks
|
78
|
+
# @option options [Array<Proc, Symbol>, Proc, Symbol] :coerce handlers for value coercion (priority over
|
79
|
+
# :coercers, :coerce_with)
|
80
|
+
# @option options [Array<Proc, Symbol>, Proc, Symbol] :coercers alias for :coerce
|
81
|
+
# @option options [Array<Proc, Symbol>, Proc, Symbol] :coerce_with alias for :coerce
|
82
|
+
# @option options [Object] :default the default value (priority over :default_generator, :default_value)
|
83
|
+
# @option options [Object] :default_generator alias for :default
|
84
|
+
# @option options [Object] :default_value alias for :default
|
85
|
+
# @option options [String] :desc short description (overridden by :description)
|
86
|
+
# @option options [String] :description description text
|
87
|
+
# @option options [Boolean] :non_nil require non-nil values (priority over :non_null, :non_nullable, :not_nil,
|
88
|
+
# :not_nilable, :not_null, :not_nullable)
|
89
|
+
# @option options [Boolean] :non_null alias for :non_nil
|
90
|
+
# @option options [Boolean] :non_nullable alias for :non_nil
|
91
|
+
# @option options [Boolean] :not_nil alias for :non_nil
|
92
|
+
# @option options [Boolean] :not_nilable alias for :non_nil
|
93
|
+
# @option options [Boolean] :not_null alias for :non_nil
|
94
|
+
# @option options [Boolean] :not_nullable alias for :non_nil
|
95
|
+
# @option options [Boolean] :null inverse of :non_nil
|
96
|
+
# @option options [Array<Proc>, Proc] :on_change alias for :callbacks
|
97
|
+
# @option options [Boolean] :optional whether attribute is optional (overridden by :required)
|
98
|
+
# @option options [Integer] :position specify order position
|
99
|
+
# @option options [Symbol] :read read visibility (:public, :protected, :private) (priority over :read_access,
|
100
|
+
# :reader)
|
101
|
+
# @option options [Symbol] :read_access alias for :read
|
102
|
+
# @option options [Symbol] :reader alias for :read
|
103
|
+
# @option options [Boolean] :required whether attribute is required
|
104
|
+
# @option options [Array<Object>, Object] :validate validators for the attribute (priority over
|
105
|
+
# :validate_with, :validators)
|
106
|
+
# @option options [Array<Object>, Object] :validate_with alias for :validate
|
107
|
+
# @option options [Array<Object>, Object] :validators alias for :validate
|
108
|
+
# @option options [Symbol] :write_access write visibility (:public, :protected, :private) (priority over
|
109
|
+
# :writer)
|
110
|
+
# @option options [Symbol] :writer alias for :write_access
|
111
|
+
#
|
112
|
+
# @yield [DSL::AttributeBuilder] configuration block for additional attribute settings
|
113
|
+
# @return [void]
|
85
114
|
# @rbs (
|
86
115
|
# String | Symbol attribute_name,
|
87
116
|
# ?Attribute::Validator::handler type_validator,
|
@@ -127,18 +156,45 @@ module Domainic
|
|
127
156
|
DSL::MethodInjector.inject!(self, attribute)
|
128
157
|
end
|
129
158
|
|
130
|
-
# Define a named option attribute
|
159
|
+
# Define a named option attribute
|
131
160
|
#
|
132
161
|
# Options are optional by default and can be provided in any order. They can be
|
133
|
-
# type-validated and configured with additional options like defaults and visibility
|
162
|
+
# type-validated and configured with additional options like defaults and visibility
|
163
|
+
#
|
164
|
+
# @see DSL::AttributeBuilder
|
165
|
+
# @see DSL::AttributeBuilder::OptionParser#initialize
|
166
|
+
#
|
167
|
+
# @example Using the options API
|
168
|
+
# class Person
|
169
|
+
# option :email, String
|
170
|
+
# option :age, ->(val) { val.is_a?(Integer) && val >= 0 }
|
171
|
+
# option :role, default: 'user'
|
172
|
+
# end
|
134
173
|
#
|
135
|
-
# @
|
174
|
+
# @example Using the block API
|
175
|
+
# class Person
|
176
|
+
# option :email, String do
|
177
|
+
# coerce_with ->(val) { val.downcase }
|
178
|
+
# validate_with ->(val) { URI::MailTo::EMAIL_REGEXP.match?(val) }
|
179
|
+
# end
|
180
|
+
#
|
181
|
+
# option :age, Integer do
|
182
|
+
# coerce_with ->(val) { val.to_i }
|
183
|
+
# validate_with ->(val) { val >= 0 }
|
184
|
+
# end
|
185
|
+
#
|
186
|
+
# option :role, String do
|
187
|
+
# validate_with ->(val) { VALID_USER_ROLES.include?(val) }
|
188
|
+
# default 'user'
|
189
|
+
# end
|
190
|
+
# end
|
191
|
+
#
|
192
|
+
# @overload option(attribute_name, type_validator = nil, **options)
|
136
193
|
# @param attribute_name [String, Symbol] the name of the attribute
|
137
194
|
# @param type_validator [Proc, Object, nil] optional validation handler for type checking
|
138
|
-
# @param options [Hash] additional configuration options
|
139
|
-
#
|
140
|
-
#
|
141
|
-
# :on_change)
|
195
|
+
# @param options [Hash{Symbol => Object}] additional configuration options
|
196
|
+
# @option options [Array<Proc>, Proc] :callbacks handlers for attribute change events (priority over
|
197
|
+
# :callback, :on_change)
|
142
198
|
# @option options [Array<Proc>, Proc] :callback alias for :callbacks
|
143
199
|
# @option options [Array<Proc, Symbol>, Proc, Symbol] :coerce handlers for value coercion (priority over
|
144
200
|
# :coercers, :coerce_with)
|
@@ -166,18 +222,15 @@ module Domainic
|
|
166
222
|
# @option options [Symbol] :read_access alias for :read
|
167
223
|
# @option options [Symbol] :reader alias for :read
|
168
224
|
# @option options [Boolean] :required whether attribute is required
|
169
|
-
# @option options [Array<Object>, Object] :validate validators for the attribute (priority over
|
170
|
-
# :validators)
|
225
|
+
# @option options [Array<Object>, Object] :validate validators for the attribute (priority over
|
226
|
+
# :validate_with, :validators)
|
171
227
|
# @option options [Array<Object>, Object] :validate_with alias for :validate
|
172
228
|
# @option options [Array<Object>, Object] :validators alias for :validate
|
173
|
-
# @option options [Symbol] :write_access write visibility (:public, :protected, :private)
|
174
|
-
#
|
229
|
+
# @option options [Symbol] :write_access write visibility (:public, :protected, :private) (priority over
|
230
|
+
# :writer)
|
175
231
|
# @option options [Symbol] :writer alias for :write_access
|
176
232
|
#
|
177
|
-
#
|
178
|
-
# @return [void]
|
179
|
-
#
|
180
|
-
# @yield [DSL::AttributeBuilder] optional configuration block
|
233
|
+
# @yield [DSL::AttributeBuilder] configuration block for additional attribute settings
|
181
234
|
# @return [void]
|
182
235
|
# @rbs (
|
183
236
|
# String | Symbol attribute_name,
|
@@ -222,10 +275,18 @@ module Domainic
|
|
222
275
|
|
223
276
|
private
|
224
277
|
|
225
|
-
#
|
278
|
+
# Get the attribute set for this class
|
279
|
+
#
|
280
|
+
# @return [AttributeSet] the set of attributes defined for this class
|
281
|
+
# @rbs () -> AttributeSet
|
282
|
+
def __attributes__
|
283
|
+
@__attributes__ ||= AttributeSet.new(self)
|
284
|
+
end
|
285
|
+
|
286
|
+
# Handle class inheritance for attributes
|
226
287
|
#
|
227
288
|
# Ensures that subclasses inherit a copy of their parent's attributes while
|
228
|
-
# maintaining proper ownership relationships
|
289
|
+
# maintaining proper ownership relationships
|
229
290
|
#
|
230
291
|
# @param subclass [Class] the inheriting class
|
231
292
|
# @return [void]
|
@@ -234,14 +295,6 @@ module Domainic
|
|
234
295
|
super
|
235
296
|
subclass.instance_variable_set(:@__attributes__, __attributes__.dup_with_base(subclass))
|
236
297
|
end
|
237
|
-
|
238
|
-
# Get the attribute set for this class.
|
239
|
-
#
|
240
|
-
# @return [AttributeSet] the set of attributes defined for this class
|
241
|
-
# @rbs () -> AttributeSet
|
242
|
-
def __attributes__
|
243
|
-
@__attributes__ ||= AttributeSet.new(self)
|
244
|
-
end
|
245
298
|
end
|
246
299
|
end
|
247
300
|
end
|