treaty 0.19.0 → 0.20.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 +1 -1
- data/lib/treaty/action/base.rb +11 -0
- data/lib/treaty/action/context/callable.rb +90 -0
- data/lib/treaty/action/context/dsl.rb +56 -0
- data/lib/treaty/action/context/workspace.rb +92 -0
- data/lib/treaty/action/executor/inventory.rb +136 -0
- data/lib/treaty/{info/rest → action/info}/builder.rb +2 -2
- data/lib/treaty/{info/rest → action/info}/dsl.rb +2 -2
- data/lib/treaty/{info/rest → action/info}/result.rb +2 -2
- data/lib/treaty/action/inventory/collection.rb +77 -0
- data/lib/treaty/action/inventory/factory.rb +108 -0
- data/lib/treaty/action/inventory/inventory.rb +146 -0
- data/lib/treaty/action/request/attribute/attribute.rb +76 -0
- data/lib/treaty/action/request/attribute/builder.rb +98 -0
- data/lib/treaty/action/request/entity.rb +78 -0
- data/lib/treaty/action/request/factory.rb +116 -0
- data/lib/treaty/action/request/validator.rb +120 -0
- data/lib/treaty/action/response/attribute/attribute.rb +79 -0
- data/lib/treaty/action/response/attribute/builder.rb +96 -0
- data/lib/treaty/action/response/entity.rb +79 -0
- data/lib/treaty/action/response/factory.rb +129 -0
- data/lib/treaty/action/response/validator.rb +111 -0
- data/lib/treaty/action/result.rb +81 -0
- data/lib/treaty/action/versions/collection.rb +47 -0
- data/lib/treaty/action/versions/dsl.rb +116 -0
- data/lib/treaty/action/versions/execution/request.rb +287 -0
- data/lib/treaty/action/versions/executor.rb +61 -0
- data/lib/treaty/action/versions/factory.rb +253 -0
- data/lib/treaty/action/versions/resolver.rb +150 -0
- data/lib/treaty/action/versions/semantic.rb +64 -0
- data/lib/treaty/action/versions/workspace.rb +106 -0
- data/lib/treaty/action.rb +31 -0
- data/lib/treaty/controller/dsl.rb +1 -1
- data/lib/treaty/entity/attribute/base.rb +1 -1
- data/lib/treaty/entity/attribute/builder/base.rb +1 -1
- data/lib/treaty/entity/attribute/dsl.rb +1 -1
- data/lib/treaty/entity/base.rb +1 -1
- data/lib/treaty/entity/builder.rb +62 -5
- data/lib/treaty/version.rb +1 -1
- metadata +32 -31
- data/lib/treaty/base.rb +0 -9
- data/lib/treaty/context/callable.rb +0 -26
- data/lib/treaty/context/dsl.rb +0 -12
- data/lib/treaty/context/workspace.rb +0 -32
- data/lib/treaty/executor/inventory.rb +0 -122
- data/lib/treaty/inventory/collection.rb +0 -71
- data/lib/treaty/inventory/factory.rb +0 -91
- data/lib/treaty/inventory/inventory.rb +0 -92
- data/lib/treaty/request/attribute/attribute.rb +0 -25
- data/lib/treaty/request/attribute/builder.rb +0 -46
- data/lib/treaty/request/entity.rb +0 -33
- data/lib/treaty/request/factory.rb +0 -81
- data/lib/treaty/request/validator.rb +0 -60
- data/lib/treaty/response/attribute/attribute.rb +0 -25
- data/lib/treaty/response/attribute/builder.rb +0 -46
- data/lib/treaty/response/entity.rb +0 -33
- data/lib/treaty/response/factory.rb +0 -87
- data/lib/treaty/response/validator.rb +0 -53
- data/lib/treaty/result.rb +0 -23
- data/lib/treaty/versions/collection.rb +0 -15
- data/lib/treaty/versions/dsl.rb +0 -42
- data/lib/treaty/versions/execution/request.rb +0 -177
- data/lib/treaty/versions/executor.rb +0 -14
- data/lib/treaty/versions/factory.rb +0 -112
- data/lib/treaty/versions/resolver.rb +0 -70
- data/lib/treaty/versions/semantic.rb +0 -22
- data/lib/treaty/versions/workspace.rb +0 -43
|
@@ -2,10 +2,64 @@
|
|
|
2
2
|
|
|
3
3
|
module Treaty
|
|
4
4
|
module Entity
|
|
5
|
-
#
|
|
5
|
+
# DSL builder for defining entity attributes.
|
|
6
|
+
#
|
|
7
|
+
# ## Purpose
|
|
8
|
+
#
|
|
9
|
+
# Provides Entity-specific implementation of the attribute builder.
|
|
10
|
+
# Creates Entity::Attribute::Attribute instances with **required by default**
|
|
11
|
+
# behavior (unlike Request/Response which have different defaults).
|
|
12
|
+
#
|
|
13
|
+
# ## Inheritance
|
|
14
|
+
#
|
|
15
|
+
# Extends Treaty::Entity::Attribute::Builder::Base which provides:
|
|
16
|
+
# - DSL interface (string, integer, object, array, etc.)
|
|
17
|
+
# - method_missing magic for type-based method calls
|
|
18
|
+
# - Helper support (:required, :optional)
|
|
19
|
+
# - Entity reuse via use_entity
|
|
20
|
+
#
|
|
21
|
+
# ## Usage
|
|
22
|
+
#
|
|
23
|
+
# Used internally by:
|
|
24
|
+
# - Entity::Attribute::Attribute (when processing nested object/array blocks)
|
|
25
|
+
#
|
|
26
|
+
# ## Default Behavior
|
|
27
|
+
#
|
|
28
|
+
# Entity attributes default to **required: true**, meaning all fields
|
|
29
|
+
# must be present unless explicitly marked `:optional`.
|
|
30
|
+
#
|
|
31
|
+
# ## DSL Example
|
|
32
|
+
#
|
|
33
|
+
# class UserEntity < Treaty::Entity::Base
|
|
34
|
+
# object :user do
|
|
35
|
+
# string :id # required by default
|
|
36
|
+
# string :name # required by default
|
|
37
|
+
# string :bio, :optional # explicitly optional
|
|
38
|
+
# object :profile do
|
|
39
|
+
# string :avatar_url
|
|
40
|
+
# end
|
|
41
|
+
# end
|
|
42
|
+
# end
|
|
43
|
+
#
|
|
44
|
+
# ## Methods
|
|
45
|
+
#
|
|
46
|
+
# Implements abstract methods from base class:
|
|
47
|
+
# - `create_attribute` - Creates Entity::Attribute::Attribute
|
|
48
|
+
# - `deep_copy_attribute` - Deep copies attribute for use_entity support
|
|
6
49
|
class Builder < Treaty::Entity::Attribute::Builder::Base
|
|
7
50
|
private
|
|
8
51
|
|
|
52
|
+
# Creates a new entity attribute instance
|
|
53
|
+
#
|
|
54
|
+
# Called by base class when defining attributes via DSL.
|
|
55
|
+
#
|
|
56
|
+
# @param name [Symbol] Attribute name
|
|
57
|
+
# @param type [Symbol] Attribute type (:string, :integer, :object, etc.)
|
|
58
|
+
# @param helpers [Array<Symbol>] Helper symbols (:required, :optional)
|
|
59
|
+
# @param nesting_level [Integer] Current nesting depth
|
|
60
|
+
# @param options [Hash] Attribute options (default:, format:, etc.)
|
|
61
|
+
# @param block [Proc] Block for nested attributes (object/array)
|
|
62
|
+
# @return [Treaty::Entity::Attribute::Attribute] Created attribute instance
|
|
9
63
|
def create_attribute(name, type, *helpers, nesting_level:, **options, &block)
|
|
10
64
|
Treaty::Entity::Attribute::Attribute.new(
|
|
11
65
|
name,
|
|
@@ -17,11 +71,14 @@ module Treaty
|
|
|
17
71
|
)
|
|
18
72
|
end
|
|
19
73
|
|
|
20
|
-
# Deep copies an attribute with adjusted nesting level
|
|
74
|
+
# Deep copies an attribute with adjusted nesting level
|
|
75
|
+
#
|
|
76
|
+
# Used when copying attributes from other Entity classes via use_entity.
|
|
77
|
+
# Recursively copies nested attributes for object/array types.
|
|
21
78
|
#
|
|
22
|
-
# @param source_attribute [Treaty::Entity::Attribute::Base]
|
|
23
|
-
# @param new_nesting_level [Integer]
|
|
24
|
-
# @return [Treaty::Entity::Attribute::Attribute]
|
|
79
|
+
# @param source_attribute [Treaty::Entity::Attribute::Base] Source attribute to copy
|
|
80
|
+
# @param new_nesting_level [Integer] Nesting level for copied attribute
|
|
81
|
+
# @return [Treaty::Entity::Attribute::Attribute] Deep copied attribute
|
|
25
82
|
def deep_copy_attribute(source_attribute, new_nesting_level) # rubocop:disable Metrics/MethodLength
|
|
26
83
|
copied = Treaty::Entity::Attribute::Attribute.new(
|
|
27
84
|
source_attribute.name,
|
data/lib/treaty/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: treaty
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.20.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Anton Sokolov
|
|
@@ -147,11 +147,38 @@ files:
|
|
|
147
147
|
- Rakefile
|
|
148
148
|
- config/locales/en.yml
|
|
149
149
|
- lib/treaty.rb
|
|
150
|
-
- lib/treaty/
|
|
150
|
+
- lib/treaty/action.rb
|
|
151
|
+
- lib/treaty/action/base.rb
|
|
152
|
+
- lib/treaty/action/context/callable.rb
|
|
153
|
+
- lib/treaty/action/context/dsl.rb
|
|
154
|
+
- lib/treaty/action/context/workspace.rb
|
|
155
|
+
- lib/treaty/action/executor/inventory.rb
|
|
156
|
+
- lib/treaty/action/info/builder.rb
|
|
157
|
+
- lib/treaty/action/info/dsl.rb
|
|
158
|
+
- lib/treaty/action/info/result.rb
|
|
159
|
+
- lib/treaty/action/inventory/collection.rb
|
|
160
|
+
- lib/treaty/action/inventory/factory.rb
|
|
161
|
+
- lib/treaty/action/inventory/inventory.rb
|
|
162
|
+
- lib/treaty/action/request/attribute/attribute.rb
|
|
163
|
+
- lib/treaty/action/request/attribute/builder.rb
|
|
164
|
+
- lib/treaty/action/request/entity.rb
|
|
165
|
+
- lib/treaty/action/request/factory.rb
|
|
166
|
+
- lib/treaty/action/request/validator.rb
|
|
167
|
+
- lib/treaty/action/response/attribute/attribute.rb
|
|
168
|
+
- lib/treaty/action/response/attribute/builder.rb
|
|
169
|
+
- lib/treaty/action/response/entity.rb
|
|
170
|
+
- lib/treaty/action/response/factory.rb
|
|
171
|
+
- lib/treaty/action/response/validator.rb
|
|
172
|
+
- lib/treaty/action/result.rb
|
|
173
|
+
- lib/treaty/action/versions/collection.rb
|
|
174
|
+
- lib/treaty/action/versions/dsl.rb
|
|
175
|
+
- lib/treaty/action/versions/execution/request.rb
|
|
176
|
+
- lib/treaty/action/versions/executor.rb
|
|
177
|
+
- lib/treaty/action/versions/factory.rb
|
|
178
|
+
- lib/treaty/action/versions/resolver.rb
|
|
179
|
+
- lib/treaty/action/versions/semantic.rb
|
|
180
|
+
- lib/treaty/action/versions/workspace.rb
|
|
151
181
|
- lib/treaty/configuration.rb
|
|
152
|
-
- lib/treaty/context/callable.rb
|
|
153
|
-
- lib/treaty/context/dsl.rb
|
|
154
|
-
- lib/treaty/context/workspace.rb
|
|
155
182
|
- lib/treaty/controller/dsl.rb
|
|
156
183
|
- lib/treaty/engine.rb
|
|
157
184
|
- lib/treaty/entity.rb
|
|
@@ -203,34 +230,8 @@ files:
|
|
|
203
230
|
- lib/treaty/exceptions/version_default_deprecated_conflict.rb
|
|
204
231
|
- lib/treaty/exceptions/version_multiple_defaults.rb
|
|
205
232
|
- lib/treaty/exceptions/version_not_found.rb
|
|
206
|
-
- lib/treaty/executor/inventory.rb
|
|
207
|
-
- lib/treaty/info/rest/builder.rb
|
|
208
|
-
- lib/treaty/info/rest/dsl.rb
|
|
209
|
-
- lib/treaty/info/rest/result.rb
|
|
210
|
-
- lib/treaty/inventory/collection.rb
|
|
211
|
-
- lib/treaty/inventory/factory.rb
|
|
212
|
-
- lib/treaty/inventory/inventory.rb
|
|
213
|
-
- lib/treaty/request/attribute/attribute.rb
|
|
214
|
-
- lib/treaty/request/attribute/builder.rb
|
|
215
|
-
- lib/treaty/request/entity.rb
|
|
216
|
-
- lib/treaty/request/factory.rb
|
|
217
|
-
- lib/treaty/request/validator.rb
|
|
218
|
-
- lib/treaty/response/attribute/attribute.rb
|
|
219
|
-
- lib/treaty/response/attribute/builder.rb
|
|
220
|
-
- lib/treaty/response/entity.rb
|
|
221
|
-
- lib/treaty/response/factory.rb
|
|
222
|
-
- lib/treaty/response/validator.rb
|
|
223
|
-
- lib/treaty/result.rb
|
|
224
233
|
- lib/treaty/support/loader.rb
|
|
225
234
|
- lib/treaty/version.rb
|
|
226
|
-
- lib/treaty/versions/collection.rb
|
|
227
|
-
- lib/treaty/versions/dsl.rb
|
|
228
|
-
- lib/treaty/versions/execution/request.rb
|
|
229
|
-
- lib/treaty/versions/executor.rb
|
|
230
|
-
- lib/treaty/versions/factory.rb
|
|
231
|
-
- lib/treaty/versions/resolver.rb
|
|
232
|
-
- lib/treaty/versions/semantic.rb
|
|
233
|
-
- lib/treaty/versions/workspace.rb
|
|
234
235
|
homepage: https://github.com/servactory/treaty
|
|
235
236
|
licenses:
|
|
236
237
|
- MIT
|
data/lib/treaty/base.rb
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Treaty
|
|
4
|
-
module Context
|
|
5
|
-
module Callable
|
|
6
|
-
def call!(version:, params:, context: nil, inventory: nil)
|
|
7
|
-
treaty_instance = send(:new)
|
|
8
|
-
|
|
9
|
-
_call!(treaty_instance, context:, inventory:, version:, params:)
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
private
|
|
13
|
-
|
|
14
|
-
def _call!(treaty_instance, context:, inventory:, version:, params:)
|
|
15
|
-
treaty_instance.send(
|
|
16
|
-
:_call!,
|
|
17
|
-
context:,
|
|
18
|
-
inventory:,
|
|
19
|
-
version:,
|
|
20
|
-
params:,
|
|
21
|
-
collection_of_versions:
|
|
22
|
-
)
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
data/lib/treaty/context/dsl.rb
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Treaty
|
|
4
|
-
module Context
|
|
5
|
-
module Workspace
|
|
6
|
-
private
|
|
7
|
-
|
|
8
|
-
def _call!(
|
|
9
|
-
context:,
|
|
10
|
-
inventory:,
|
|
11
|
-
version:,
|
|
12
|
-
params:,
|
|
13
|
-
collection_of_versions:
|
|
14
|
-
)
|
|
15
|
-
call!(
|
|
16
|
-
context:,
|
|
17
|
-
inventory:,
|
|
18
|
-
version:,
|
|
19
|
-
params:,
|
|
20
|
-
collection_of_versions:
|
|
21
|
-
)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def call!(
|
|
25
|
-
collection_of_versions:,
|
|
26
|
-
**
|
|
27
|
-
)
|
|
28
|
-
@collection_of_versions = collection_of_versions
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Treaty
|
|
4
|
-
module Executor
|
|
5
|
-
# Inventory wrapper that provides method-based access to inventory items.
|
|
6
|
-
#
|
|
7
|
-
# ## Purpose
|
|
8
|
-
#
|
|
9
|
-
# Wraps inventory collection and controller context, providing lazy evaluation
|
|
10
|
-
# of inventory items through method calls. This encapsulates all inventory logic
|
|
11
|
-
# within the class and provides a clean API for services.
|
|
12
|
-
#
|
|
13
|
-
# ## Usage
|
|
14
|
-
#
|
|
15
|
-
# ```ruby
|
|
16
|
-
# # Created internally by Treaty
|
|
17
|
-
# inventory = Treaty::Executor::Inventory.new(inventory_collection, controller_context)
|
|
18
|
-
#
|
|
19
|
-
# # Access via method calls - evaluates lazily
|
|
20
|
-
# inventory.posts # => Calls controller method or evaluates proc
|
|
21
|
-
# inventory.current_user # => Returns evaluated value
|
|
22
|
-
#
|
|
23
|
-
# # Raises exception for missing items
|
|
24
|
-
# inventory.missing_item # => Treaty::Exceptions::Inventory
|
|
25
|
-
#
|
|
26
|
-
# # Convert to hash - evaluates all items
|
|
27
|
-
# inventory.to_h # => { posts: [...], current_user: ... }
|
|
28
|
-
# ```
|
|
29
|
-
#
|
|
30
|
-
# ## Architecture
|
|
31
|
-
#
|
|
32
|
-
# The class encapsulates:
|
|
33
|
-
# - Inventory collection (from controller's treaty block)
|
|
34
|
-
# - Controller context (for method calls and proc evaluation)
|
|
35
|
-
# - Lazy evaluation logic (items evaluated on access)
|
|
36
|
-
#
|
|
37
|
-
# ## Error Handling
|
|
38
|
-
#
|
|
39
|
-
# If an inventory item is not found, raises `Treaty::Exceptions::Inventory` with
|
|
40
|
-
# an I18n-translated error message listing available items.
|
|
41
|
-
class Inventory
|
|
42
|
-
# Creates a new inventory instance
|
|
43
|
-
#
|
|
44
|
-
# @param inventory [Treaty::Inventory::Collection] Collection of inventory items
|
|
45
|
-
# @param context [Object] Controller instance for evaluation
|
|
46
|
-
def initialize(inventory, context)
|
|
47
|
-
@inventory = inventory
|
|
48
|
-
@context = context
|
|
49
|
-
@evaluated_cache = {}
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# Provides method-based access to inventory items with lazy evaluation
|
|
53
|
-
#
|
|
54
|
-
# @param method_name [Symbol] The inventory item name
|
|
55
|
-
# @param _args [Array] Arguments (not used, for compatibility)
|
|
56
|
-
# @return [Object] The evaluated inventory item value
|
|
57
|
-
# @raise [Treaty::Exceptions::Inventory] If item not found
|
|
58
|
-
def method_missing(method_name, *_args)
|
|
59
|
-
# Check cache first
|
|
60
|
-
return @evaluated_cache[method_name] if @evaluated_cache.key?(method_name)
|
|
61
|
-
|
|
62
|
-
# Find inventory item
|
|
63
|
-
item = find_inventory_item(method_name)
|
|
64
|
-
|
|
65
|
-
# Evaluate and cache
|
|
66
|
-
@evaluated_cache[method_name] = item.evaluate(@context)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
# Checks if inventory responds to a method
|
|
70
|
-
#
|
|
71
|
-
# @param method_name [Symbol] The method name to check
|
|
72
|
-
# @param include_private [Boolean] Whether to include private methods
|
|
73
|
-
# @return [Boolean] True if inventory has the item
|
|
74
|
-
def respond_to_missing?(method_name, include_private = false)
|
|
75
|
-
return false if @inventory.nil?
|
|
76
|
-
|
|
77
|
-
@inventory.names.include?(method_name) || super
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
# Converts inventory to hash, evaluating all items
|
|
81
|
-
#
|
|
82
|
-
# @return [Hash] Hash of all evaluated inventory items
|
|
83
|
-
def to_h
|
|
84
|
-
return {} if @inventory.nil?
|
|
85
|
-
|
|
86
|
-
@inventory.evaluate(@context)
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
# Returns string representation
|
|
90
|
-
#
|
|
91
|
-
# @return [String] Inventory description
|
|
92
|
-
def inspect
|
|
93
|
-
items = @inventory&.names || []
|
|
94
|
-
"#<Treaty::Executor::Inventory items=#{items.inspect}>"
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
private
|
|
98
|
-
|
|
99
|
-
# Finds inventory item by name
|
|
100
|
-
#
|
|
101
|
-
# @param name [Symbol] Inventory item name
|
|
102
|
-
# @return [Treaty::Inventory::Inventory] The inventory item
|
|
103
|
-
# @raise [Treaty::Exceptions::Inventory] If not found or inventory is nil
|
|
104
|
-
def find_inventory_item(name)
|
|
105
|
-
# Use find method for cleaner search
|
|
106
|
-
item = @inventory&.find { |item| item.name == name }
|
|
107
|
-
|
|
108
|
-
return item if item
|
|
109
|
-
|
|
110
|
-
# Item not found - list available items
|
|
111
|
-
available = @inventory&.names || []
|
|
112
|
-
|
|
113
|
-
raise Treaty::Exceptions::Inventory,
|
|
114
|
-
I18n.t(
|
|
115
|
-
"treaty.executor.inventory.item_not_found",
|
|
116
|
-
name:,
|
|
117
|
-
available: available.join(", ")
|
|
118
|
-
)
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
end
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Treaty
|
|
4
|
-
module Inventory
|
|
5
|
-
# Collection wrapper for sets of inventory items.
|
|
6
|
-
#
|
|
7
|
-
# ## Purpose
|
|
8
|
-
#
|
|
9
|
-
# Provides a unified interface for working with collections of inventory items.
|
|
10
|
-
# Uses Ruby Set internally for uniqueness but exposes Array-like interface.
|
|
11
|
-
#
|
|
12
|
-
# ## Usage
|
|
13
|
-
#
|
|
14
|
-
# Used internally by:
|
|
15
|
-
# - Inventory::Factory (to store inventory items during DSL processing)
|
|
16
|
-
#
|
|
17
|
-
# ## Methods
|
|
18
|
-
#
|
|
19
|
-
# Delegates common collection methods to internal Set:
|
|
20
|
-
# - `<<` - Add inventory item
|
|
21
|
-
# - `empty?` - Check if collection is empty
|
|
22
|
-
#
|
|
23
|
-
# Custom methods:
|
|
24
|
-
# - `exists?` - Returns true if collection is not empty
|
|
25
|
-
# - `evaluate` - Evaluates all inventory items with context
|
|
26
|
-
#
|
|
27
|
-
# ## Example
|
|
28
|
-
#
|
|
29
|
-
# collection = Collection.new
|
|
30
|
-
# collection << Inventory.new(name: :posts, source: :load_posts)
|
|
31
|
-
# collection << Inventory.new(name: :meta, source: -> { { count: 10 } })
|
|
32
|
-
# collection.size # => 2
|
|
33
|
-
# collection.exists? # => true
|
|
34
|
-
class Collection
|
|
35
|
-
extend Forwardable
|
|
36
|
-
|
|
37
|
-
def_delegators :@collection, :<<, :each_with_object, :find, :empty?
|
|
38
|
-
|
|
39
|
-
# Creates a new collection instance
|
|
40
|
-
#
|
|
41
|
-
# @param collection [Set] Initial collection (default: empty Set)
|
|
42
|
-
def initialize(collection = Set.new)
|
|
43
|
-
@collection = collection
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
# Checks if collection has any elements
|
|
47
|
-
#
|
|
48
|
-
# @return [Boolean] True if collection is not empty
|
|
49
|
-
def exists?
|
|
50
|
-
!empty?
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
# Returns array of all inventory item names
|
|
54
|
-
#
|
|
55
|
-
# @return [Array<Symbol>] Array of inventory item names
|
|
56
|
-
def names
|
|
57
|
-
@collection.each_with_object([]) { |item, names| names << item.name }
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
# Evaluates all inventory items with the given context
|
|
61
|
-
#
|
|
62
|
-
# @param context [Object] The controller instance to call methods on
|
|
63
|
-
# @return [Hash{Symbol => Object}] Hash of inventory name => resolved value
|
|
64
|
-
def evaluate(context)
|
|
65
|
-
@collection.each_with_object({}) do |inventory_item, hash|
|
|
66
|
-
hash[inventory_item.name] = inventory_item.evaluate(context)
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Treaty
|
|
4
|
-
module Inventory
|
|
5
|
-
# Factory for building inventory collections via DSL.
|
|
6
|
-
#
|
|
7
|
-
# ## Purpose
|
|
8
|
-
#
|
|
9
|
-
# Provides the `provide` DSL method for defining inventory items in controller blocks.
|
|
10
|
-
# Captures calls like `provide :posts, from: :load_posts` and builds a collection.
|
|
11
|
-
#
|
|
12
|
-
# ## Usage
|
|
13
|
-
#
|
|
14
|
-
# Used internally by Controller::DSL when processing treaty blocks:
|
|
15
|
-
#
|
|
16
|
-
# ```ruby
|
|
17
|
-
# treaty :index do
|
|
18
|
-
# provide :posts, from: :load_posts # Explicit source
|
|
19
|
-
# provide :meta, from: -> { { count: 10 } } # Lambda source
|
|
20
|
-
# provide :current_user # Shorthand: uses :current_user as source
|
|
21
|
-
# end
|
|
22
|
-
# ```
|
|
23
|
-
#
|
|
24
|
-
# ## Valid Sources
|
|
25
|
-
#
|
|
26
|
-
# - Symbol: Method name to call on controller (e.g., `:load_posts`)
|
|
27
|
-
# - Proc/Lambda: Callable object (e.g., `-> { Post.all }`)
|
|
28
|
-
# - Direct value: String, number, or any other value (e.g., `"Welcome"`)
|
|
29
|
-
# - Omitted: Uses inventory name as source (e.g., `provide :posts` → `from: :posts`)
|
|
30
|
-
#
|
|
31
|
-
# ## Invalid Sources
|
|
32
|
-
#
|
|
33
|
-
# - Direct method calls without symbol/proc (e.g., `from: load_posts`)
|
|
34
|
-
# - Explicit nil values (e.g., `from: nil`)
|
|
35
|
-
class Factory
|
|
36
|
-
attr_reader :collection
|
|
37
|
-
|
|
38
|
-
def initialize(action_name)
|
|
39
|
-
@action_name = action_name
|
|
40
|
-
@collection = Collection.new
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# Handles the `provide` DSL method via method_missing
|
|
44
|
-
#
|
|
45
|
-
# @param method_name [Symbol] Should be :provide
|
|
46
|
-
# @param args [Array] First argument is the inventory name
|
|
47
|
-
# @param options [Hash] Optional :from key with source (defaults to inventory name)
|
|
48
|
-
# @return [Collection] The collection being built
|
|
49
|
-
# @raise [Treaty::Exceptions::Inventory] For invalid method or missing parameters
|
|
50
|
-
def method_missing(method_name, *args, **options, &_block) # rubocop:disable Metrics/MethodLength
|
|
51
|
-
# Only handle 'provide' method
|
|
52
|
-
unless method_name == :provide
|
|
53
|
-
raise Treaty::Exceptions::Inventory,
|
|
54
|
-
I18n.t(
|
|
55
|
-
"treaty.inventory.unknown_method",
|
|
56
|
-
method: method_name,
|
|
57
|
-
action: @action_name
|
|
58
|
-
)
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# Extract inventory name
|
|
62
|
-
inventory_name = args.first
|
|
63
|
-
|
|
64
|
-
unless inventory_name.is_a?(Symbol)
|
|
65
|
-
raise Treaty::Exceptions::Inventory,
|
|
66
|
-
I18n.t(
|
|
67
|
-
"treaty.inventory.name_must_be_symbol",
|
|
68
|
-
name: inventory_name.inspect
|
|
69
|
-
)
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# Extract source from options (default to inventory name if not provided)
|
|
73
|
-
source = if options.key?(:from)
|
|
74
|
-
options.fetch(:from)
|
|
75
|
-
else
|
|
76
|
-
inventory_name
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
# Create and add inventory item to collection
|
|
80
|
-
@collection << Inventory.new(name: inventory_name, source:)
|
|
81
|
-
|
|
82
|
-
# Return collection for potential chaining
|
|
83
|
-
@collection
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def respond_to_missing?(method_name, *)
|
|
87
|
-
method_name == :provide || super
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Treaty
|
|
4
|
-
module Inventory
|
|
5
|
-
# Represents a single inventory item that provides data to the treaty execution.
|
|
6
|
-
#
|
|
7
|
-
# An inventory item has a name and a source. The source can be:
|
|
8
|
-
# - Symbol: A method name to call on the controller (e.g., :load_posts)
|
|
9
|
-
# - Proc/Lambda: A callable object (e.g., -> { Post.all })
|
|
10
|
-
# - Direct value: Any other value to pass directly (e.g., "text", 42)
|
|
11
|
-
#
|
|
12
|
-
# ## Usage
|
|
13
|
-
#
|
|
14
|
-
# ```ruby
|
|
15
|
-
# # In controller
|
|
16
|
-
# treaty :index do
|
|
17
|
-
# provide :posts, from: :load_posts
|
|
18
|
-
# provide :meta, from: -> { { count: 10 } }
|
|
19
|
-
# provide :title, from: "Welcome"
|
|
20
|
-
# end
|
|
21
|
-
# ```
|
|
22
|
-
class Inventory
|
|
23
|
-
attr_reader :name, :source
|
|
24
|
-
|
|
25
|
-
def initialize(name:, source:)
|
|
26
|
-
validate_name!(name)
|
|
27
|
-
validate_source!(source)
|
|
28
|
-
|
|
29
|
-
@name = name
|
|
30
|
-
@source = source
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# Evaluates the inventory source with the given context
|
|
34
|
-
#
|
|
35
|
-
# @param context [Object] The controller instance to call methods on
|
|
36
|
-
# @return [Object] The resolved value
|
|
37
|
-
# @raise [Treaty::Exceptions::Inventory] If evaluation fails
|
|
38
|
-
def evaluate(context) # rubocop:disable Metrics/MethodLength
|
|
39
|
-
case source
|
|
40
|
-
when Symbol
|
|
41
|
-
evaluate_symbol(context)
|
|
42
|
-
when Proc
|
|
43
|
-
evaluate_proc(context)
|
|
44
|
-
else
|
|
45
|
-
source
|
|
46
|
-
end
|
|
47
|
-
rescue StandardError => e
|
|
48
|
-
raise Treaty::Exceptions::Inventory,
|
|
49
|
-
I18n.t(
|
|
50
|
-
"treaty.inventory.evaluation_error",
|
|
51
|
-
name: @name,
|
|
52
|
-
error: e.message
|
|
53
|
-
)
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
private
|
|
57
|
-
|
|
58
|
-
# Evaluates Symbol source by calling method on context
|
|
59
|
-
#
|
|
60
|
-
# @param context [Object] The controller instance
|
|
61
|
-
# @return [Object] The method return value
|
|
62
|
-
def evaluate_symbol(context)
|
|
63
|
-
context.send(source)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
# Evaluates Proc source within controller context
|
|
67
|
-
#
|
|
68
|
-
# @param context [Object] The controller instance
|
|
69
|
-
# @return [Object] The proc return value
|
|
70
|
-
def evaluate_proc(context)
|
|
71
|
-
# Execute proc in controller context to access instance variables and methods
|
|
72
|
-
context.instance_exec(&source)
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def validate_name!(name)
|
|
76
|
-
return if name.is_a?(Symbol) && !name.to_s.empty?
|
|
77
|
-
|
|
78
|
-
raise Treaty::Exceptions::Inventory,
|
|
79
|
-
I18n.t("treaty.inventory.invalid_name", name: name.inspect)
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def validate_source!(source)
|
|
83
|
-
# Source must be Symbol, Proc, or any other direct value
|
|
84
|
-
# We don't allow nil as it's likely a mistake
|
|
85
|
-
return unless source.nil?
|
|
86
|
-
|
|
87
|
-
raise Treaty::Exceptions::Inventory,
|
|
88
|
-
I18n.t("treaty.inventory.source_required")
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
end
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Treaty
|
|
4
|
-
module Request
|
|
5
|
-
module Attribute
|
|
6
|
-
# Request-specific attribute that defaults to required: true
|
|
7
|
-
class Attribute < Treaty::Entity::Attribute::Base
|
|
8
|
-
private
|
|
9
|
-
|
|
10
|
-
def apply_defaults!
|
|
11
|
-
# For request: required by default (true).
|
|
12
|
-
# message: nil means use I18n default message from validators
|
|
13
|
-
@options[:required] ||= { is: true, message: nil }
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def process_nested_attributes(&block)
|
|
17
|
-
return unless object_or_array?
|
|
18
|
-
|
|
19
|
-
builder = Builder.new(collection_of_attributes, @nesting_level + 1)
|
|
20
|
-
builder.instance_eval(&block)
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|