treaty 0.17.0 → 0.19.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 +4 -4
- data/README.md +2 -2
- data/config/locales/en.yml +6 -2
- data/lib/treaty/engine.rb +1 -1
- data/lib/treaty/{attribute/entity → entity/attribute}/attribute.rb +4 -4
- data/lib/treaty/entity/attribute/base.rb +184 -0
- data/lib/treaty/entity/attribute/builder/base.rb +275 -0
- data/lib/treaty/entity/attribute/collection.rb +67 -0
- data/lib/treaty/entity/attribute/dsl.rb +92 -0
- data/lib/treaty/entity/attribute/helper_mapper.rb +74 -0
- data/lib/treaty/entity/attribute/option/base.rb +190 -0
- data/lib/treaty/entity/attribute/option/conditionals/base.rb +92 -0
- data/lib/treaty/entity/attribute/option/conditionals/if_conditional.rb +136 -0
- data/lib/treaty/entity/attribute/option/conditionals/unless_conditional.rb +153 -0
- data/lib/treaty/entity/attribute/option/modifiers/as_modifier.rb +93 -0
- data/lib/treaty/entity/attribute/option/modifiers/cast_modifier.rb +285 -0
- data/lib/treaty/entity/attribute/option/modifiers/computed_modifier.rb +128 -0
- data/lib/treaty/entity/attribute/option/modifiers/default_modifier.rb +105 -0
- data/lib/treaty/entity/attribute/option/modifiers/transform_modifier.rb +114 -0
- data/lib/treaty/entity/attribute/option/registry.rb +157 -0
- data/lib/treaty/entity/attribute/option/registry_initializer.rb +117 -0
- data/lib/treaty/entity/attribute/option/validators/format_validator.rb +222 -0
- data/lib/treaty/entity/attribute/option/validators/inclusion_validator.rb +94 -0
- data/lib/treaty/entity/attribute/option/validators/required_validator.rb +100 -0
- data/lib/treaty/entity/attribute/option/validators/type_validator.rb +219 -0
- data/lib/treaty/entity/attribute/option_normalizer.rb +168 -0
- data/lib/treaty/entity/attribute/option_orchestrator.rb +192 -0
- data/lib/treaty/entity/attribute/validation/attribute_validator.rb +147 -0
- data/lib/treaty/entity/attribute/validation/base.rb +76 -0
- data/lib/treaty/entity/attribute/validation/nested_array_validator.rb +207 -0
- data/lib/treaty/entity/attribute/validation/nested_object_validator.rb +105 -0
- data/lib/treaty/entity/attribute/validation/nested_transformer.rb +432 -0
- data/lib/treaty/entity/attribute/validation/orchestrator/base.rb +262 -0
- data/lib/treaty/entity/base.rb +90 -0
- data/lib/treaty/entity/builder.rb +44 -0
- data/lib/treaty/{info/entity → entity/info}/builder.rb +8 -8
- data/lib/treaty/{info/entity → entity/info}/dsl.rb +2 -2
- data/lib/treaty/{info/entity → entity/info}/result.rb +2 -2
- data/lib/treaty/entity.rb +7 -75
- data/lib/treaty/request/attribute/attribute.rb +1 -1
- data/lib/treaty/request/attribute/builder.rb +24 -1
- data/lib/treaty/request/entity.rb +1 -1
- data/lib/treaty/request/factory.rb +6 -6
- data/lib/treaty/request/validator.rb +1 -1
- data/lib/treaty/response/attribute/attribute.rb +1 -1
- data/lib/treaty/response/attribute/builder.rb +24 -1
- data/lib/treaty/response/entity.rb +1 -1
- data/lib/treaty/response/factory.rb +6 -6
- data/lib/treaty/response/validator.rb +1 -1
- data/lib/treaty/version.rb +1 -1
- metadata +35 -34
- data/lib/treaty/attribute/base.rb +0 -182
- data/lib/treaty/attribute/builder/base.rb +0 -143
- data/lib/treaty/attribute/collection.rb +0 -65
- data/lib/treaty/attribute/dsl.rb +0 -90
- data/lib/treaty/attribute/entity/builder.rb +0 -23
- data/lib/treaty/attribute/helper_mapper.rb +0 -72
- data/lib/treaty/attribute/option/base.rb +0 -188
- data/lib/treaty/attribute/option/conditionals/base.rb +0 -90
- data/lib/treaty/attribute/option/conditionals/if_conditional.rb +0 -134
- data/lib/treaty/attribute/option/conditionals/unless_conditional.rb +0 -151
- data/lib/treaty/attribute/option/modifiers/as_modifier.rb +0 -91
- data/lib/treaty/attribute/option/modifiers/cast_modifier.rb +0 -283
- data/lib/treaty/attribute/option/modifiers/computed_modifier.rb +0 -126
- data/lib/treaty/attribute/option/modifiers/default_modifier.rb +0 -103
- data/lib/treaty/attribute/option/modifiers/transform_modifier.rb +0 -112
- data/lib/treaty/attribute/option/registry.rb +0 -155
- data/lib/treaty/attribute/option/registry_initializer.rb +0 -115
- data/lib/treaty/attribute/option/validators/format_validator.rb +0 -220
- data/lib/treaty/attribute/option/validators/inclusion_validator.rb +0 -92
- data/lib/treaty/attribute/option/validators/required_validator.rb +0 -98
- data/lib/treaty/attribute/option/validators/type_validator.rb +0 -217
- data/lib/treaty/attribute/option_normalizer.rb +0 -166
- data/lib/treaty/attribute/option_orchestrator.rb +0 -190
- data/lib/treaty/attribute/validation/attribute_validator.rb +0 -145
- data/lib/treaty/attribute/validation/base.rb +0 -74
- data/lib/treaty/attribute/validation/nested_array_validator.rb +0 -205
- data/lib/treaty/attribute/validation/nested_object_validator.rb +0 -103
- data/lib/treaty/attribute/validation/nested_transformer.rb +0 -430
- data/lib/treaty/attribute/validation/orchestrator/base.rb +0 -260
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Treaty
|
|
4
|
-
module Attribute
|
|
5
|
-
# Base class for all attribute definitions in Treaty DSL.
|
|
6
|
-
#
|
|
7
|
-
# ## Purpose
|
|
8
|
-
#
|
|
9
|
-
# Represents a single attribute defined in request/response definitions.
|
|
10
|
-
# Handles:
|
|
11
|
-
# - Attribute metadata (name, type, nesting level)
|
|
12
|
-
# - Helper mode to simple mode conversion
|
|
13
|
-
# - Simple mode to advanced mode normalization
|
|
14
|
-
# - Nested attributes (for object and array types)
|
|
15
|
-
#
|
|
16
|
-
# ## Usage
|
|
17
|
-
#
|
|
18
|
-
# Attributes are created through DSL methods:
|
|
19
|
-
# string :title, :required
|
|
20
|
-
# integer :age, default: 18
|
|
21
|
-
# object :author do
|
|
22
|
-
# string :name
|
|
23
|
-
# end
|
|
24
|
-
#
|
|
25
|
-
# ## Processing Flow
|
|
26
|
-
#
|
|
27
|
-
# 1. Extract helpers from arguments (`:required`, `:optional`)
|
|
28
|
-
# 2. Convert helpers to simple mode options
|
|
29
|
-
# 3. Merge with explicit options
|
|
30
|
-
# 4. Normalize all options to advanced mode
|
|
31
|
-
# 5. Apply defaults (required: true for request, false for response)
|
|
32
|
-
# 6. Process nested attributes if block given
|
|
33
|
-
#
|
|
34
|
-
# ## Nested Attributes
|
|
35
|
-
#
|
|
36
|
-
# Object and array types can have nested attributes:
|
|
37
|
-
# - `object` - nested attributes as direct children
|
|
38
|
-
# - `array` - nested attributes define array element structure
|
|
39
|
-
#
|
|
40
|
-
# Special attribute name `:_self` is used for simple arrays:
|
|
41
|
-
# array :tags do
|
|
42
|
-
# string :_self # Array of strings
|
|
43
|
-
# end
|
|
44
|
-
class Base
|
|
45
|
-
attr_reader :name,
|
|
46
|
-
:type,
|
|
47
|
-
:options,
|
|
48
|
-
:nesting_level
|
|
49
|
-
|
|
50
|
-
# Creates a new attribute instance
|
|
51
|
-
#
|
|
52
|
-
# @param name [Symbol] The attribute name
|
|
53
|
-
# @param type [Symbol] The attribute type (:string, :integer, :object, :array, etc.)
|
|
54
|
-
# @param helpers [Array<Symbol>] Helper symbols (:required, :optional)
|
|
55
|
-
# @param nesting_level [Integer] Current nesting depth (default: 0)
|
|
56
|
-
# @param options [Hash] Attribute options (required, default, as, etc.)
|
|
57
|
-
# @param block [Proc] Block for defining nested attributes (for object/array types)
|
|
58
|
-
def initialize(name, type, *helpers, nesting_level: 0, **options, &block)
|
|
59
|
-
@name = name
|
|
60
|
-
@type = type
|
|
61
|
-
@nesting_level = nesting_level
|
|
62
|
-
|
|
63
|
-
validate_nesting_level!
|
|
64
|
-
|
|
65
|
-
# Separate helpers from non-helper symbols.
|
|
66
|
-
@helpers = extract_helpers(helpers)
|
|
67
|
-
|
|
68
|
-
# Merge helper options with explicit options.
|
|
69
|
-
merged_options = merge_options(@helpers, options)
|
|
70
|
-
|
|
71
|
-
# Normalize all options to advanced mode.
|
|
72
|
-
@options = OptionNormalizer.normalize(merged_options)
|
|
73
|
-
|
|
74
|
-
apply_defaults!
|
|
75
|
-
|
|
76
|
-
# Process nested attributes for object and array types.
|
|
77
|
-
process_nested_attributes(&block) if block_given?
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
# Returns collection of nested attributes for this attribute
|
|
81
|
-
#
|
|
82
|
-
# @return [Collection] Collection of nested attributes
|
|
83
|
-
def collection_of_attributes
|
|
84
|
-
@collection_of_attributes ||= Collection.new
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
# Checks if this attribute has nested attributes
|
|
88
|
-
#
|
|
89
|
-
# @return [Boolean] True if attribute is object/array with nested attributes
|
|
90
|
-
def nested?
|
|
91
|
-
object_or_array? && collection_of_attributes.exists?
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
# Checks if this attribute is an object or array type
|
|
95
|
-
#
|
|
96
|
-
# @return [Boolean] True if type is :object or :array
|
|
97
|
-
def object_or_array?
|
|
98
|
-
object? || array?
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
# Checks if this attribute is an object type
|
|
102
|
-
#
|
|
103
|
-
# @return [Boolean] True if type is :object
|
|
104
|
-
def object?
|
|
105
|
-
@type == :object
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
# Checks if this attribute is an array type
|
|
109
|
-
#
|
|
110
|
-
# @return [Boolean] True if type is :array
|
|
111
|
-
def array?
|
|
112
|
-
@type == :array
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
private
|
|
116
|
-
|
|
117
|
-
# Validates that nesting level doesn't exceed maximum allowed depth
|
|
118
|
-
#
|
|
119
|
-
# @raise [Treaty::Exceptions::NestedAttributes] If nesting exceeds limit
|
|
120
|
-
# @return [void]
|
|
121
|
-
def validate_nesting_level!
|
|
122
|
-
return unless @nesting_level > Treaty::Engine.config.treaty.attribute_nesting_level
|
|
123
|
-
|
|
124
|
-
raise Treaty::Exceptions::NestedAttributes,
|
|
125
|
-
I18n.t(
|
|
126
|
-
"treaty.attributes.errors.nesting_level_exceeded",
|
|
127
|
-
level: @nesting_level,
|
|
128
|
-
max_level: Treaty::Engine.config.treaty.attribute_nesting_level
|
|
129
|
-
)
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
# Extracts helper symbols from arguments
|
|
133
|
-
#
|
|
134
|
-
# @param helpers [Array] Mixed array that may contain helper symbols
|
|
135
|
-
# @return [Array<Symbol>] Filtered array of valid helper symbols
|
|
136
|
-
def extract_helpers(helpers)
|
|
137
|
-
helpers.select do |helper|
|
|
138
|
-
helper.is_a?(Symbol) && HelperMapper.helper?(helper)
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
# Merges helper-derived options with explicit options
|
|
143
|
-
#
|
|
144
|
-
# @param helpers [Array<Symbol>] Helper symbols to convert
|
|
145
|
-
# @param explicit_options [Hash] Explicitly provided options
|
|
146
|
-
# @return [Hash] Merged options hash
|
|
147
|
-
def merge_options(helpers, explicit_options)
|
|
148
|
-
helper_options = HelperMapper.map(helpers)
|
|
149
|
-
helper_options.merge(explicit_options)
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
# Applies default values for options based on context (request/response)
|
|
153
|
-
# Must be implemented in subclasses
|
|
154
|
-
#
|
|
155
|
-
# @raise [Treaty::Exceptions::NotImplemented] If subclass doesn't implement
|
|
156
|
-
# @return [void]
|
|
157
|
-
def apply_defaults!
|
|
158
|
-
# Must be implemented in subclasses
|
|
159
|
-
raise Treaty::Exceptions::NotImplemented,
|
|
160
|
-
I18n.t(
|
|
161
|
-
"treaty.attributes.errors.apply_defaults_not_implemented",
|
|
162
|
-
class: self.class
|
|
163
|
-
)
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
# Processes nested attributes block for object/array types
|
|
167
|
-
# Must be implemented in subclasses
|
|
168
|
-
#
|
|
169
|
-
# @param block [Proc] Block containing nested attribute definitions
|
|
170
|
-
# @raise [Treaty::Exceptions::NotImplemented] If subclass doesn't implement
|
|
171
|
-
# @return [void]
|
|
172
|
-
def process_nested_attributes
|
|
173
|
-
# Must be implemented in subclasses
|
|
174
|
-
raise Treaty::Exceptions::NotImplemented,
|
|
175
|
-
I18n.t(
|
|
176
|
-
"treaty.attributes.errors.process_nested_not_implemented",
|
|
177
|
-
class: self.class
|
|
178
|
-
)
|
|
179
|
-
end
|
|
180
|
-
end
|
|
181
|
-
end
|
|
182
|
-
end
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Treaty
|
|
4
|
-
module Attribute
|
|
5
|
-
module Builder
|
|
6
|
-
# Base DSL builder for defining attributes in request/response definitions.
|
|
7
|
-
#
|
|
8
|
-
# ## Purpose
|
|
9
|
-
#
|
|
10
|
-
# Provides the DSL interface for defining attributes within objects.
|
|
11
|
-
# Handles method_missing magic to support type-based method calls.
|
|
12
|
-
#
|
|
13
|
-
# ## Responsibilities
|
|
14
|
-
#
|
|
15
|
-
# 1. **DSL Interface** - Provides clean syntax for attribute definitions
|
|
16
|
-
# 2. **Method Dispatch** - Routes type methods (string, integer, etc.) to attribute creation
|
|
17
|
-
# 3. **Helper Support** - Handles helper symbols in various positions
|
|
18
|
-
# 4. **Nesting Tracking** - Tracks nesting level for nested attributes
|
|
19
|
-
#
|
|
20
|
-
# ## DSL Usage
|
|
21
|
-
#
|
|
22
|
-
# The builder enables this clean DSL syntax:
|
|
23
|
-
#
|
|
24
|
-
# ```ruby
|
|
25
|
-
# request do
|
|
26
|
-
# object :user do
|
|
27
|
-
# string :name
|
|
28
|
-
# integer :age, default: 18
|
|
29
|
-
# object :profile do
|
|
30
|
-
# string :bio
|
|
31
|
-
# end
|
|
32
|
-
# end
|
|
33
|
-
# end
|
|
34
|
-
# ```
|
|
35
|
-
#
|
|
36
|
-
# ## Method Dispatch
|
|
37
|
-
#
|
|
38
|
-
# ### Type-based Methods
|
|
39
|
-
# When you call `string :name`, it routes through `method_missing`:
|
|
40
|
-
# 1. `string` becomes the type
|
|
41
|
-
# 2. `:name` becomes the attribute name
|
|
42
|
-
# 3. Calls `attribute(:name, :string, ...)`
|
|
43
|
-
#
|
|
44
|
-
# ### Helper Position Handling
|
|
45
|
-
# Handles helpers in different positions:
|
|
46
|
-
#
|
|
47
|
-
# ```ruby
|
|
48
|
-
# string :required, :name # Helper first, then name
|
|
49
|
-
# string :name, :required # Name first, then helper
|
|
50
|
-
# ```
|
|
51
|
-
#
|
|
52
|
-
# Both resolve to the same attribute definition.
|
|
53
|
-
#
|
|
54
|
-
# ## Nesting
|
|
55
|
-
#
|
|
56
|
-
# Tracks nesting level for:
|
|
57
|
-
# - Validation (enforcing maximum nesting depth)
|
|
58
|
-
# - Error messages (showing context)
|
|
59
|
-
#
|
|
60
|
-
# Maximum nesting level is configured in Treaty::Engine.config.
|
|
61
|
-
#
|
|
62
|
-
# ## Subclass Requirements
|
|
63
|
-
#
|
|
64
|
-
# Subclasses must implement:
|
|
65
|
-
# - `create_attribute` - Creates the appropriate attribute type (Request/Response)
|
|
66
|
-
#
|
|
67
|
-
# ## Architecture
|
|
68
|
-
#
|
|
69
|
-
# Used by:
|
|
70
|
-
# - Request::Builder - For request attribute definitions
|
|
71
|
-
# - Response::Builder - For response attribute definitions
|
|
72
|
-
class Base
|
|
73
|
-
attr_reader :nesting_level,
|
|
74
|
-
:collection_of_attributes
|
|
75
|
-
|
|
76
|
-
# Creates a new builder instance
|
|
77
|
-
#
|
|
78
|
-
# @param collection_of_attributes [Collection] Collection to add attributes to
|
|
79
|
-
# @param nesting_level [Integer] Current nesting depth
|
|
80
|
-
def initialize(collection_of_attributes, nesting_level)
|
|
81
|
-
@collection_of_attributes = collection_of_attributes
|
|
82
|
-
@nesting_level = nesting_level
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
# Defines an attribute with explicit type
|
|
86
|
-
#
|
|
87
|
-
# @param name [Symbol] The attribute name
|
|
88
|
-
# @param type [Symbol] The attribute type
|
|
89
|
-
# @param helpers [Array<Symbol>] Helper symbols (:required, :optional)
|
|
90
|
-
# @param options [Hash] Attribute options
|
|
91
|
-
# @param block [Proc] Block for nested attributes
|
|
92
|
-
# @return [void]
|
|
93
|
-
def attribute(name, type, *helpers, **options, &block)
|
|
94
|
-
@collection_of_attributes << create_attribute(
|
|
95
|
-
name,
|
|
96
|
-
type,
|
|
97
|
-
*helpers,
|
|
98
|
-
nesting_level: @nesting_level,
|
|
99
|
-
**options,
|
|
100
|
-
&block
|
|
101
|
-
)
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
# Handles DSL methods like `string :name` where method name is the type
|
|
105
|
-
#
|
|
106
|
-
# @param type [Symbol] The attribute type (method name)
|
|
107
|
-
# @param name [Symbol] The attribute name (first argument)
|
|
108
|
-
# @param helpers [Array<Symbol>] Helper symbols
|
|
109
|
-
# @param options [Hash] Attribute options
|
|
110
|
-
# @param block [Proc] Block for nested attributes
|
|
111
|
-
# @return [void]
|
|
112
|
-
def method_missing(type, name, *helpers, **options, &block)
|
|
113
|
-
if name.is_a?(Symbol) && HelperMapper.helper?(name)
|
|
114
|
-
helpers.unshift(name)
|
|
115
|
-
name = helpers.shift
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
attribute(name, type, *helpers, **options, &block)
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
# Checks if method should be handled by method_missing
|
|
122
|
-
#
|
|
123
|
-
# @param name [Symbol] Method name
|
|
124
|
-
# @return [Boolean]
|
|
125
|
-
def respond_to_missing?(name, *)
|
|
126
|
-
super
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
private
|
|
130
|
-
|
|
131
|
-
# Creates an attribute instance (must be implemented in subclasses)
|
|
132
|
-
#
|
|
133
|
-
# @raise [Treaty::Exceptions::NotImplemented] If subclass doesn't implement
|
|
134
|
-
# @return [Attribute::Base] Created attribute instance
|
|
135
|
-
def create_attribute(*)
|
|
136
|
-
# Must be implemented in subclasses
|
|
137
|
-
raise Treaty::Exceptions::NotImplemented,
|
|
138
|
-
I18n.t("treaty.attributes.builder.not_implemented", class: self.class)
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
end
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "forwardable"
|
|
4
|
-
|
|
5
|
-
module Treaty
|
|
6
|
-
module Attribute
|
|
7
|
-
# Collection wrapper for sets of attributes.
|
|
8
|
-
#
|
|
9
|
-
# ## Purpose
|
|
10
|
-
#
|
|
11
|
-
# Provides a unified interface for working with collections of attributes.
|
|
12
|
-
# Uses Ruby Set internally for uniqueness but exposes Array-like interface.
|
|
13
|
-
#
|
|
14
|
-
# ## Usage
|
|
15
|
-
#
|
|
16
|
-
# Used internally by:
|
|
17
|
-
# - Request/Response factories (to store attributes)
|
|
18
|
-
# - Attribute::Base (to store nested attributes)
|
|
19
|
-
#
|
|
20
|
-
# ## Methods
|
|
21
|
-
#
|
|
22
|
-
# Delegates common collection methods to internal Set:
|
|
23
|
-
# - `<<` - Add attribute
|
|
24
|
-
# - `each`, `map`, `select`, `reject` - Iteration
|
|
25
|
-
# - `find`, `first` - Access
|
|
26
|
-
# - `size`, `empty?` - Size checks
|
|
27
|
-
# - `to_h` - Convert to hash
|
|
28
|
-
#
|
|
29
|
-
# Custom methods:
|
|
30
|
-
# - `exists?` - Returns true if collection is not empty
|
|
31
|
-
#
|
|
32
|
-
# ## Example
|
|
33
|
-
#
|
|
34
|
-
# collection = Collection.new
|
|
35
|
-
# collection << Attribute::Base.new(:name, :string)
|
|
36
|
-
# collection << Attribute::Base.new(:age, :integer)
|
|
37
|
-
# collection.size # => 2
|
|
38
|
-
# collection.exists? # => true
|
|
39
|
-
class Collection
|
|
40
|
-
extend Forwardable
|
|
41
|
-
|
|
42
|
-
def_delegators :@collection,
|
|
43
|
-
:<<,
|
|
44
|
-
:to_h, :map,
|
|
45
|
-
:each_with_object, :each,
|
|
46
|
-
:select, :reject, :size,
|
|
47
|
-
:find, :first,
|
|
48
|
-
:empty?
|
|
49
|
-
|
|
50
|
-
# Creates a new collection instance
|
|
51
|
-
#
|
|
52
|
-
# @param collection [Set] Initial collection (default: empty Set)
|
|
53
|
-
def initialize(collection = Set.new)
|
|
54
|
-
@collection = collection
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# Checks if collection has any elements
|
|
58
|
-
#
|
|
59
|
-
# @return [Boolean] True if collection is not empty
|
|
60
|
-
def exists?
|
|
61
|
-
!empty?
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|
data/lib/treaty/attribute/dsl.rb
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Treaty
|
|
4
|
-
module Attribute
|
|
5
|
-
# DSL module for defining attributes in Entity-like classes.
|
|
6
|
-
#
|
|
7
|
-
# This module provides the class-level DSL for defining attributes.
|
|
8
|
-
# It can be included in any class that needs attribute definition capabilities.
|
|
9
|
-
#
|
|
10
|
-
# ## Usage
|
|
11
|
-
#
|
|
12
|
-
# ```ruby
|
|
13
|
-
# class MyEntity
|
|
14
|
-
# include Treaty::Attribute::DSL
|
|
15
|
-
#
|
|
16
|
-
# string :name
|
|
17
|
-
# integer :age
|
|
18
|
-
# end
|
|
19
|
-
# ```
|
|
20
|
-
module DSL
|
|
21
|
-
def self.included(base)
|
|
22
|
-
base.extend(ClassMethods)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
module ClassMethods
|
|
26
|
-
# Defines an attribute with explicit type
|
|
27
|
-
#
|
|
28
|
-
# @param name [Symbol] The attribute name
|
|
29
|
-
# @param type [Symbol] The attribute type
|
|
30
|
-
# @param helpers [Array<Symbol>] Helper symbols (:required, :optional)
|
|
31
|
-
# @param options [Hash] Attribute options
|
|
32
|
-
# @param block [Proc] Block for nested attributes
|
|
33
|
-
# @return [void]
|
|
34
|
-
def attribute(name, type, *helpers, **options, &block)
|
|
35
|
-
collection_of_attributes << create_attribute(
|
|
36
|
-
name,
|
|
37
|
-
type,
|
|
38
|
-
*helpers,
|
|
39
|
-
nesting_level: 0,
|
|
40
|
-
**options,
|
|
41
|
-
&block
|
|
42
|
-
)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# Returns collection of attributes for this class
|
|
46
|
-
#
|
|
47
|
-
# @return [Collection] Collection of attributes
|
|
48
|
-
def collection_of_attributes
|
|
49
|
-
@collection_of_attributes ||= Treaty::Attribute::Collection.new
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# Handles DSL methods like `string :name` where method name is the type
|
|
53
|
-
#
|
|
54
|
-
# @param type [Symbol] The attribute type (method name)
|
|
55
|
-
# @param name [Symbol] The attribute name (first argument)
|
|
56
|
-
# @param helpers [Array<Symbol>] Helper symbols
|
|
57
|
-
# @param options [Hash] Attribute options
|
|
58
|
-
# @param block [Proc] Block for nested attributes
|
|
59
|
-
# @return [void]
|
|
60
|
-
def method_missing(type, *helpers, **options, &block)
|
|
61
|
-
name = helpers.shift
|
|
62
|
-
|
|
63
|
-
# If no attribute name provided, this is not an attribute definition
|
|
64
|
-
# Pass to super to handle it properly (e.g., for methods like 'info', 'call!', etc.)
|
|
65
|
-
return super if name.nil?
|
|
66
|
-
|
|
67
|
-
attribute(name, type, *helpers, **options, &block)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def respond_to_missing?(name, *)
|
|
71
|
-
super
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
private
|
|
75
|
-
|
|
76
|
-
# Creates an attribute instance (must be implemented by including class)
|
|
77
|
-
#
|
|
78
|
-
# @raise [Treaty::Exceptions::NotImplemented] If not implemented
|
|
79
|
-
# @return [Attribute::Base] Created attribute instance
|
|
80
|
-
def create_attribute(*)
|
|
81
|
-
raise Treaty::Exceptions::NotImplemented,
|
|
82
|
-
I18n.t(
|
|
83
|
-
"treaty.attributes.dsl.create_attribute_not_implemented",
|
|
84
|
-
class: self
|
|
85
|
-
)
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
end
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Treaty
|
|
4
|
-
module Attribute
|
|
5
|
-
module Entity
|
|
6
|
-
# Entity-specific attribute builder
|
|
7
|
-
class Builder < Treaty::Attribute::Builder::Base
|
|
8
|
-
private
|
|
9
|
-
|
|
10
|
-
def create_attribute(name, type, *helpers, nesting_level:, **options, &block)
|
|
11
|
-
Attribute.new(
|
|
12
|
-
name,
|
|
13
|
-
type,
|
|
14
|
-
*helpers,
|
|
15
|
-
nesting_level:,
|
|
16
|
-
**options,
|
|
17
|
-
&block
|
|
18
|
-
)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Treaty
|
|
4
|
-
module Attribute
|
|
5
|
-
# Maps DSL helper symbols to their simple mode option equivalents.
|
|
6
|
-
#
|
|
7
|
-
# ## Purpose
|
|
8
|
-
#
|
|
9
|
-
# Helpers provide the most concise syntax for common options.
|
|
10
|
-
# They are syntactic sugar that gets converted to simple mode options.
|
|
11
|
-
#
|
|
12
|
-
# ## Available Helpers
|
|
13
|
-
#
|
|
14
|
-
# - `:required` → `required: true`
|
|
15
|
-
# - `:optional` → `required: false`
|
|
16
|
-
#
|
|
17
|
-
# ## Usage Examples
|
|
18
|
-
#
|
|
19
|
-
# Helper mode (most concise):
|
|
20
|
-
# string :title, :required
|
|
21
|
-
# string :bio, :optional
|
|
22
|
-
#
|
|
23
|
-
# Equivalent to simple mode:
|
|
24
|
-
# string :title, required: true
|
|
25
|
-
# string :bio, required: false
|
|
26
|
-
#
|
|
27
|
-
# ## Processing Flow
|
|
28
|
-
#
|
|
29
|
-
# 1. Helper mode: `string :title, :required`
|
|
30
|
-
# 2. HelperMapper: `:required` → `required: true`
|
|
31
|
-
# 3. OptionNormalizer: `required: true` → `{ is: true, message: nil }`
|
|
32
|
-
# 4. Final: Advanced mode used internally
|
|
33
|
-
#
|
|
34
|
-
# ## Adding New Helpers
|
|
35
|
-
#
|
|
36
|
-
# To add a new helper:
|
|
37
|
-
# ```ruby
|
|
38
|
-
# HELPER_MAPPINGS = {
|
|
39
|
-
# required: { required: true },
|
|
40
|
-
# optional: { required: false },
|
|
41
|
-
# my_helper: { my_option: :smth } # New helper example
|
|
42
|
-
# }.freeze
|
|
43
|
-
# ```
|
|
44
|
-
class HelperMapper
|
|
45
|
-
HELPER_MAPPINGS = {
|
|
46
|
-
required: { required: true },
|
|
47
|
-
optional: { required: false }
|
|
48
|
-
}.freeze
|
|
49
|
-
|
|
50
|
-
class << self
|
|
51
|
-
# Maps helper symbols to their simple mode equivalents
|
|
52
|
-
#
|
|
53
|
-
# @param helpers [Array<Symbol>] Array of helper symbols
|
|
54
|
-
# @return [Hash] Simple mode options hash
|
|
55
|
-
def map(helpers)
|
|
56
|
-
helpers.each_with_object({}) do |helper, result|
|
|
57
|
-
mapping = HELPER_MAPPINGS.fetch(helper)
|
|
58
|
-
result.merge!(mapping) if mapping.present?
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
# Checks if a symbol is a registered helper
|
|
63
|
-
#
|
|
64
|
-
# @param symbol [Symbol] Symbol to check
|
|
65
|
-
# @return [Boolean] True if symbol is a helper
|
|
66
|
-
def helper?(symbol)
|
|
67
|
-
HELPER_MAPPINGS.key?(symbol)
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
end
|