cmdx 1.1.2 → 1.5.1
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/.DS_Store +0 -0
- data/.cursor/prompts/docs.md +4 -1
- data/.cursor/prompts/llms.md +20 -0
- data/.cursor/prompts/rspec.md +4 -1
- data/.cursor/prompts/yardoc.md +3 -2
- data/.cursor/rules/cursor-instructions.mdc +55 -1
- data/.irbrc +6 -0
- data/.rubocop.yml +29 -18
- data/CHANGELOG.md +11 -132
- data/LLM.md +3317 -0
- data/README.md +68 -44
- data/docs/attributes/coercions.md +162 -0
- data/docs/attributes/defaults.md +90 -0
- data/docs/attributes/definitions.md +281 -0
- data/docs/attributes/naming.md +78 -0
- data/docs/attributes/validations.md +309 -0
- data/docs/basics/chain.md +56 -249
- data/docs/basics/context.md +56 -289
- data/docs/basics/execution.md +114 -0
- data/docs/basics/setup.md +37 -334
- data/docs/callbacks.md +89 -467
- data/docs/deprecation.md +91 -174
- data/docs/getting_started.md +212 -202
- data/docs/internationalization.md +11 -647
- data/docs/interruptions/exceptions.md +23 -198
- data/docs/interruptions/faults.md +71 -151
- data/docs/interruptions/halt.md +109 -186
- data/docs/logging.md +44 -256
- data/docs/middlewares.md +113 -426
- data/docs/outcomes/result.md +81 -228
- data/docs/outcomes/states.md +33 -221
- data/docs/outcomes/statuses.md +21 -311
- data/docs/tips_and_tricks.md +120 -70
- data/docs/workflows.md +99 -283
- data/lib/cmdx/.DS_Store +0 -0
- data/lib/cmdx/attribute.rb +229 -0
- data/lib/cmdx/attribute_registry.rb +94 -0
- data/lib/cmdx/attribute_value.rb +193 -0
- data/lib/cmdx/callback_registry.rb +69 -77
- data/lib/cmdx/chain.rb +56 -73
- data/lib/cmdx/coercion_registry.rb +52 -68
- data/lib/cmdx/coercions/array.rb +19 -18
- data/lib/cmdx/coercions/big_decimal.rb +20 -24
- data/lib/cmdx/coercions/boolean.rb +26 -25
- data/lib/cmdx/coercions/complex.rb +21 -22
- data/lib/cmdx/coercions/date.rb +25 -23
- data/lib/cmdx/coercions/date_time.rb +24 -25
- data/lib/cmdx/coercions/float.rb +25 -22
- data/lib/cmdx/coercions/hash.rb +31 -32
- data/lib/cmdx/coercions/integer.rb +30 -24
- data/lib/cmdx/coercions/rational.rb +29 -24
- data/lib/cmdx/coercions/string.rb +19 -22
- data/lib/cmdx/coercions/symbol.rb +37 -0
- data/lib/cmdx/coercions/time.rb +26 -25
- data/lib/cmdx/configuration.rb +49 -108
- data/lib/cmdx/context.rb +222 -44
- data/lib/cmdx/deprecator.rb +61 -0
- data/lib/cmdx/errors.rb +42 -252
- data/lib/cmdx/exceptions.rb +39 -0
- data/lib/cmdx/faults.rb +78 -39
- data/lib/cmdx/freezer.rb +51 -0
- data/lib/cmdx/identifier.rb +30 -0
- data/lib/cmdx/locale.rb +52 -0
- data/lib/cmdx/log_formatters/json.rb +21 -22
- data/lib/cmdx/log_formatters/key_value.rb +20 -22
- data/lib/cmdx/log_formatters/line.rb +15 -22
- data/lib/cmdx/log_formatters/logstash.rb +22 -23
- data/lib/cmdx/log_formatters/raw.rb +16 -22
- data/lib/cmdx/middleware_registry.rb +70 -74
- data/lib/cmdx/middlewares/correlate.rb +90 -54
- data/lib/cmdx/middlewares/runtime.rb +58 -0
- data/lib/cmdx/middlewares/timeout.rb +48 -68
- data/lib/cmdx/railtie.rb +12 -45
- data/lib/cmdx/result.rb +229 -314
- data/lib/cmdx/task.rb +194 -366
- data/lib/cmdx/utils/call.rb +49 -0
- data/lib/cmdx/utils/condition.rb +71 -0
- data/lib/cmdx/utils/format.rb +61 -0
- data/lib/cmdx/validator_registry.rb +63 -72
- data/lib/cmdx/validators/exclusion.rb +38 -67
- data/lib/cmdx/validators/format.rb +48 -49
- data/lib/cmdx/validators/inclusion.rb +43 -74
- data/lib/cmdx/validators/length.rb +101 -162
- data/lib/cmdx/validators/numeric.rb +95 -170
- data/lib/cmdx/validators/presence.rb +37 -50
- data/lib/cmdx/version.rb +1 -1
- data/lib/cmdx/worker.rb +178 -0
- data/lib/cmdx/workflow.rb +85 -81
- data/lib/cmdx.rb +19 -13
- data/lib/generators/cmdx/install_generator.rb +14 -13
- data/lib/generators/cmdx/task_generator.rb +25 -50
- data/lib/generators/cmdx/templates/install.rb +11 -46
- data/lib/generators/cmdx/templates/task.rb.tt +3 -2
- data/lib/locales/en.yml +18 -4
- data/src/cmdx-logo.png +0 -0
- metadata +32 -116
- data/docs/ai_prompts.md +0 -393
- data/docs/basics/call.md +0 -317
- data/docs/configuration.md +0 -344
- data/docs/parameters/coercions.md +0 -396
- data/docs/parameters/defaults.md +0 -335
- data/docs/parameters/definitions.md +0 -446
- data/docs/parameters/namespacing.md +0 -378
- data/docs/parameters/validations.md +0 -405
- data/docs/testing.md +0 -553
- data/lib/cmdx/callback.rb +0 -53
- data/lib/cmdx/chain_inspector.rb +0 -56
- data/lib/cmdx/chain_serializer.rb +0 -63
- data/lib/cmdx/coercion.rb +0 -57
- data/lib/cmdx/coercions/virtual.rb +0 -29
- data/lib/cmdx/core_ext/hash.rb +0 -83
- data/lib/cmdx/core_ext/module.rb +0 -98
- data/lib/cmdx/core_ext/object.rb +0 -125
- data/lib/cmdx/correlator.rb +0 -122
- data/lib/cmdx/error.rb +0 -67
- data/lib/cmdx/fault.rb +0 -140
- data/lib/cmdx/immutator.rb +0 -52
- data/lib/cmdx/lazy_struct.rb +0 -246
- data/lib/cmdx/log_formatters/pretty_json.rb +0 -40
- data/lib/cmdx/log_formatters/pretty_key_value.rb +0 -38
- data/lib/cmdx/log_formatters/pretty_line.rb +0 -41
- data/lib/cmdx/logger.rb +0 -49
- data/lib/cmdx/logger_ansi.rb +0 -68
- data/lib/cmdx/logger_serializer.rb +0 -116
- data/lib/cmdx/middleware.rb +0 -70
- data/lib/cmdx/parameter.rb +0 -312
- data/lib/cmdx/parameter_evaluator.rb +0 -231
- data/lib/cmdx/parameter_inspector.rb +0 -66
- data/lib/cmdx/parameter_registry.rb +0 -106
- data/lib/cmdx/parameter_serializer.rb +0 -59
- data/lib/cmdx/result_ansi.rb +0 -71
- data/lib/cmdx/result_inspector.rb +0 -71
- data/lib/cmdx/result_logger.rb +0 -59
- data/lib/cmdx/result_serializer.rb +0 -104
- data/lib/cmdx/rspec/matchers.rb +0 -28
- data/lib/cmdx/rspec/result_matchers/be_executed.rb +0 -42
- data/lib/cmdx/rspec/result_matchers/be_failed_task.rb +0 -94
- data/lib/cmdx/rspec/result_matchers/be_skipped_task.rb +0 -94
- data/lib/cmdx/rspec/result_matchers/be_state_matchers.rb +0 -59
- data/lib/cmdx/rspec/result_matchers/be_status_matchers.rb +0 -57
- data/lib/cmdx/rspec/result_matchers/be_successful_task.rb +0 -87
- data/lib/cmdx/rspec/result_matchers/have_bad_outcome.rb +0 -51
- data/lib/cmdx/rspec/result_matchers/have_caused_failure.rb +0 -58
- data/lib/cmdx/rspec/result_matchers/have_chain_index.rb +0 -59
- data/lib/cmdx/rspec/result_matchers/have_context.rb +0 -86
- data/lib/cmdx/rspec/result_matchers/have_empty_metadata.rb +0 -54
- data/lib/cmdx/rspec/result_matchers/have_good_outcome.rb +0 -52
- data/lib/cmdx/rspec/result_matchers/have_metadata.rb +0 -114
- data/lib/cmdx/rspec/result_matchers/have_preserved_context.rb +0 -66
- data/lib/cmdx/rspec/result_matchers/have_received_thrown_failure.rb +0 -64
- data/lib/cmdx/rspec/result_matchers/have_runtime.rb +0 -78
- data/lib/cmdx/rspec/result_matchers/have_thrown_failure.rb +0 -76
- data/lib/cmdx/rspec/task_matchers/be_well_formed_task.rb +0 -62
- data/lib/cmdx/rspec/task_matchers/have_callback.rb +0 -85
- data/lib/cmdx/rspec/task_matchers/have_cmd_setting.rb +0 -68
- data/lib/cmdx/rspec/task_matchers/have_executed_callbacks.rb +0 -92
- data/lib/cmdx/rspec/task_matchers/have_middleware.rb +0 -46
- data/lib/cmdx/rspec/task_matchers/have_parameter.rb +0 -181
- data/lib/cmdx/task_deprecator.rb +0 -58
- data/lib/cmdx/task_processor.rb +0 -246
- data/lib/cmdx/task_serializer.rb +0 -57
- data/lib/cmdx/utils/ansi_color.rb +0 -73
- data/lib/cmdx/utils/log_timestamp.rb +0 -36
- data/lib/cmdx/utils/monotonic_runtime.rb +0 -34
- data/lib/cmdx/utils/name_affix.rb +0 -52
- data/lib/cmdx/validator.rb +0 -57
- data/lib/generators/cmdx/templates/workflow.rb.tt +0 -7
- data/lib/generators/cmdx/workflow_generator.rb +0 -84
- data/lib/locales/ar.yml +0 -35
- data/lib/locales/cs.yml +0 -35
- data/lib/locales/da.yml +0 -35
- data/lib/locales/de.yml +0 -35
- data/lib/locales/el.yml +0 -35
- data/lib/locales/es.yml +0 -35
- data/lib/locales/fi.yml +0 -35
- data/lib/locales/fr.yml +0 -35
- data/lib/locales/he.yml +0 -35
- data/lib/locales/hi.yml +0 -35
- data/lib/locales/it.yml +0 -35
- data/lib/locales/ja.yml +0 -35
- data/lib/locales/ko.yml +0 -35
- data/lib/locales/nl.yml +0 -35
- data/lib/locales/no.yml +0 -35
- data/lib/locales/pl.yml +0 -35
- data/lib/locales/pt.yml +0 -35
- data/lib/locales/ru.yml +0 -35
- data/lib/locales/sv.yml +0 -35
- data/lib/locales/th.yml +0 -35
- data/lib/locales/tr.yml +0 -35
- data/lib/locales/vi.yml +0 -35
- data/lib/locales/zh.yml +0 -35
@@ -1,446 +0,0 @@
|
|
1
|
-
# Parameters - Definitions
|
2
|
-
|
3
|
-
Parameters define the interface between task callers and implementation, enabling automatic validation, type coercion, and method generation. They provide a contract to verify that task execution arguments match expected requirements and structure.
|
4
|
-
|
5
|
-
## Table of Contents
|
6
|
-
|
7
|
-
- [TLDR](#tldr)
|
8
|
-
- [Basic Parameter Definition](#basic-parameter-definition)
|
9
|
-
- [Parameter Sources](#parameter-sources)
|
10
|
-
- [Nested Parameters](#nested-parameters)
|
11
|
-
- [Advanced Features](#advanced-features)
|
12
|
-
- [Error Handling](#error-handling)
|
13
|
-
|
14
|
-
## TLDR
|
15
|
-
|
16
|
-
```ruby
|
17
|
-
class ProcessOrderTask < CMDx::Task
|
18
|
-
# Required parameters - must be provided
|
19
|
-
required :order_id, :customer_id
|
20
|
-
|
21
|
-
# Optional parameters - can be nil
|
22
|
-
optional :notes, :priority
|
23
|
-
|
24
|
-
# Custom sources
|
25
|
-
required :name, :email, source: :user
|
26
|
-
|
27
|
-
# Nested parameters
|
28
|
-
required :shipping_address do
|
29
|
-
required :street, :city, :state
|
30
|
-
optional :apartment
|
31
|
-
end
|
32
|
-
|
33
|
-
def call
|
34
|
-
order_id # → value from call arguments
|
35
|
-
name # → delegates to user.name
|
36
|
-
street # → delegates to shipping_address.street
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
# Usage
|
41
|
-
ProcessOrderTask.call(
|
42
|
-
order_id: 123,
|
43
|
-
customer_id: 456,
|
44
|
-
shipping_address: { street: "123 Main St", city: "Miami", state: "FL" }
|
45
|
-
)
|
46
|
-
```
|
47
|
-
|
48
|
-
## Basic Parameter Definition
|
49
|
-
|
50
|
-
> [!IMPORTANT]
|
51
|
-
> Required parameters must be provided in call arguments or task execution will fail. Optional parameters return `nil` when not provided.
|
52
|
-
|
53
|
-
```ruby
|
54
|
-
class CreateUserTask < CMDx::Task
|
55
|
-
# Single parameter definitions
|
56
|
-
required :email
|
57
|
-
optional :name
|
58
|
-
|
59
|
-
# Multiple parameters in one declaration
|
60
|
-
required :age, :phone
|
61
|
-
optional :bio, :website
|
62
|
-
|
63
|
-
# Parameters with type coercion and validation
|
64
|
-
required :age, type: :integer, numeric: { min: 18 }
|
65
|
-
optional :tags, type: :array, default: []
|
66
|
-
|
67
|
-
def call
|
68
|
-
# All parameters become instance methods
|
69
|
-
user = User.create!(
|
70
|
-
email: email, # Required - guaranteed to be present
|
71
|
-
name: name, # Optional - may be nil
|
72
|
-
age: age, # Required integer, validated >= 18
|
73
|
-
phone: phone, # Required - guaranteed to be present
|
74
|
-
bio: bio, # Optional - may be nil
|
75
|
-
tags: tags # Optional array with default []
|
76
|
-
)
|
77
|
-
|
78
|
-
user
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# Parameters passed as keyword arguments
|
83
|
-
CreateUserTask.call(
|
84
|
-
email: "user@example.com",
|
85
|
-
age: 25,
|
86
|
-
phone: "555-0123",
|
87
|
-
name: "John Doe",
|
88
|
-
tags: ["premium", "beta"]
|
89
|
-
)
|
90
|
-
```
|
91
|
-
|
92
|
-
## Parameter Sources
|
93
|
-
|
94
|
-
Parameters delegate to source objects within the task context. The default source is `:context`, but any accessible method or object can serve as a parameter source.
|
95
|
-
|
96
|
-
> [!NOTE]
|
97
|
-
> Sources allow parameters to pull values from different objects instead of just call arguments.
|
98
|
-
|
99
|
-
### Default Context Source
|
100
|
-
|
101
|
-
```ruby
|
102
|
-
class UpdateProfileTask < CMDx::Task
|
103
|
-
# Default source is :context
|
104
|
-
required :user_id
|
105
|
-
optional :avatar_url
|
106
|
-
|
107
|
-
# Explicitly specify context source
|
108
|
-
required :email, source: :context
|
109
|
-
|
110
|
-
def call
|
111
|
-
user = User.find(user_id) # From context.user_id
|
112
|
-
user.update!(
|
113
|
-
email: email, # From context.email
|
114
|
-
avatar_url: avatar_url # From context.avatar_url
|
115
|
-
)
|
116
|
-
end
|
117
|
-
end
|
118
|
-
```
|
119
|
-
|
120
|
-
### Custom Object Sources
|
121
|
-
|
122
|
-
```ruby
|
123
|
-
class GenerateInvoiceTask < CMDx::Task
|
124
|
-
# Delegate to user object
|
125
|
-
required :name, :email, source: :user
|
126
|
-
|
127
|
-
# Delegate to order object
|
128
|
-
required :total, :items, source: :order
|
129
|
-
optional :discount, source: :order
|
130
|
-
|
131
|
-
def call
|
132
|
-
Invoice.create!(
|
133
|
-
customer_name: name, # From user.name
|
134
|
-
customer_email: email, # From user.email
|
135
|
-
amount: total, # From order.total
|
136
|
-
line_items: items, # From order.items
|
137
|
-
discount_amount: discount # From order.discount
|
138
|
-
)
|
139
|
-
end
|
140
|
-
|
141
|
-
private
|
142
|
-
|
143
|
-
def user
|
144
|
-
@user ||= User.find(context.user_id)
|
145
|
-
end
|
146
|
-
|
147
|
-
def order
|
148
|
-
@order ||= user.orders.find(context.order_id)
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
GenerateInvoiceTask.call(user_id: 123, order_id: 456)
|
153
|
-
```
|
154
|
-
|
155
|
-
### Dynamic Sources
|
156
|
-
|
157
|
-
```ruby
|
158
|
-
class CalculatePermissionsTask < CMDx::Task
|
159
|
-
# Proc/Lambda source for dynamic resolution
|
160
|
-
required :current_user, source: ->(task) { User.find(task.context.user_id) }
|
161
|
-
required :company_name, source: proc { Company.find_by(context.company_id).name }
|
162
|
-
|
163
|
-
# Method symbol sources
|
164
|
-
required :role, source: :determine_user_role
|
165
|
-
optional :access_level, source: :calculate_access_level
|
166
|
-
|
167
|
-
def call
|
168
|
-
{
|
169
|
-
user: current_user.name, # Resolved via lambda
|
170
|
-
company: company_name, # Resolved via proc
|
171
|
-
role: role, # From determine_user_role method
|
172
|
-
access: access_level # From calculate_access_level method
|
173
|
-
}
|
174
|
-
end
|
175
|
-
|
176
|
-
private
|
177
|
-
|
178
|
-
def determine_user_role
|
179
|
-
current_user.admin? ? "admin" : "user"
|
180
|
-
end
|
181
|
-
|
182
|
-
def calculate_access_level
|
183
|
-
case role
|
184
|
-
when "admin" then "full"
|
185
|
-
when "user" then "limited"
|
186
|
-
else "none"
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
```
|
191
|
-
|
192
|
-
## Nested Parameters
|
193
|
-
|
194
|
-
Nested parameters enable complex parameter structures where child parameters automatically inherit their parent as the source. This allows validation and access of structured data.
|
195
|
-
|
196
|
-
> [!TIP]
|
197
|
-
> Child parameters are only required when their parent parameter is provided, enabling flexible optional structures.
|
198
|
-
|
199
|
-
```ruby
|
200
|
-
class CreateShipmentTask < CMDx::Task
|
201
|
-
required :order_id
|
202
|
-
|
203
|
-
# Required parent with required children
|
204
|
-
required :shipping_address do
|
205
|
-
required :street, :city, :state, :zip
|
206
|
-
optional :apartment, :instructions
|
207
|
-
end
|
208
|
-
|
209
|
-
# Optional parent with conditional children
|
210
|
-
optional :billing_address do
|
211
|
-
required :street, :city # Only required if billing_address provided
|
212
|
-
optional :same_as_shipping
|
213
|
-
end
|
214
|
-
|
215
|
-
# Multi-level nesting
|
216
|
-
optional :special_handling do
|
217
|
-
required :type
|
218
|
-
|
219
|
-
optional :insurance do
|
220
|
-
required :coverage_amount, type: :float
|
221
|
-
optional :carrier
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
def call
|
226
|
-
shipment = Shipment.create!(
|
227
|
-
order_id: order_id,
|
228
|
-
|
229
|
-
# Access nested parameters directly
|
230
|
-
ship_to_street: street, # From shipping_address.street
|
231
|
-
ship_to_city: city, # From shipping_address.city
|
232
|
-
ship_to_state: state, # From shipping_address.state
|
233
|
-
delivery_instructions: instructions,
|
234
|
-
|
235
|
-
# Handle optional nested structures
|
236
|
-
special_handling_type: type, # From special_handling.type (if provided)
|
237
|
-
insurance_amount: coverage_amount # From special_handling.insurance.coverage_amount
|
238
|
-
)
|
239
|
-
|
240
|
-
shipment
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
CreateShipmentTask.call(
|
245
|
-
order_id: 123,
|
246
|
-
shipping_address: {
|
247
|
-
street: "123 Main St",
|
248
|
-
city: "Miami",
|
249
|
-
state: "FL",
|
250
|
-
zip: "33101",
|
251
|
-
instructions: "Leave at door"
|
252
|
-
},
|
253
|
-
special_handling: {
|
254
|
-
type: "fragile",
|
255
|
-
insurance: {
|
256
|
-
coverage_amount: 500.00,
|
257
|
-
carrier: "FedEx"
|
258
|
-
}
|
259
|
-
}
|
260
|
-
)
|
261
|
-
```
|
262
|
-
|
263
|
-
## Advanced Features
|
264
|
-
|
265
|
-
### Parameter Method Generation
|
266
|
-
|
267
|
-
```ruby
|
268
|
-
class ProcessPaymentTask < CMDx::Task
|
269
|
-
required :amount, type: :float
|
270
|
-
required :payment_method
|
271
|
-
|
272
|
-
# Nested parameters generate flattened methods
|
273
|
-
required :customer do
|
274
|
-
required :id, :email
|
275
|
-
|
276
|
-
optional :billing_address do
|
277
|
-
required :street, :city
|
278
|
-
optional :unit
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
|
-
def call
|
283
|
-
# All parameters accessible as instance methods
|
284
|
-
payment = PaymentService.charge(
|
285
|
-
amount: amount, # Direct parameter access
|
286
|
-
method: payment_method, # Direct parameter access
|
287
|
-
customer_id: id, # From customer.id
|
288
|
-
customer_email: email, # From customer.email
|
289
|
-
billing_street: street, # From customer.billing_address.street
|
290
|
-
billing_city: city # From customer.billing_address.city
|
291
|
-
)
|
292
|
-
|
293
|
-
payment
|
294
|
-
end
|
295
|
-
end
|
296
|
-
```
|
297
|
-
|
298
|
-
### Parameter Introspection
|
299
|
-
|
300
|
-
```ruby
|
301
|
-
class IntrospectionExampleTask < CMDx::Task
|
302
|
-
required :name
|
303
|
-
optional :age, type: :integer, default: 18
|
304
|
-
|
305
|
-
required :address do
|
306
|
-
required :street
|
307
|
-
optional :unit
|
308
|
-
end
|
309
|
-
|
310
|
-
def call
|
311
|
-
# Access parameter metadata
|
312
|
-
params = self.class.parameters
|
313
|
-
|
314
|
-
params.each do |param|
|
315
|
-
puts "Parameter: #{param.name}"
|
316
|
-
puts "Required: #{param.required?}"
|
317
|
-
puts "Type: #{param.type}"
|
318
|
-
puts "Default: #{param.default}" if param.has_default?
|
319
|
-
puts "Source: #{param.source}"
|
320
|
-
puts "---"
|
321
|
-
end
|
322
|
-
end
|
323
|
-
end
|
324
|
-
```
|
325
|
-
|
326
|
-
## Error Handling
|
327
|
-
|
328
|
-
> [!WARNING]
|
329
|
-
> Parameter validation failures result in structured error information with details about each failed parameter.
|
330
|
-
|
331
|
-
### Missing Required Parameters
|
332
|
-
|
333
|
-
```ruby
|
334
|
-
class RequiredParamsTask < CMDx::Task
|
335
|
-
required :user_id, :order_id
|
336
|
-
required :shipping_address do
|
337
|
-
required :street, :city
|
338
|
-
end
|
339
|
-
|
340
|
-
def call
|
341
|
-
# Task logic
|
342
|
-
end
|
343
|
-
end
|
344
|
-
|
345
|
-
# Missing required parameters
|
346
|
-
result = RequiredParamsTask.call(user_id: 123)
|
347
|
-
result.failed? # → true
|
348
|
-
result.metadata
|
349
|
-
# {
|
350
|
-
# reason: "order_id is required. shipping_address is required.",
|
351
|
-
# messages: {
|
352
|
-
# order_id: ["is required"],
|
353
|
-
# shipping_address: ["is required"]
|
354
|
-
# }
|
355
|
-
# }
|
356
|
-
|
357
|
-
# Missing nested required parameters
|
358
|
-
result = RequiredParamsTask.call(
|
359
|
-
user_id: 123,
|
360
|
-
order_id: 456,
|
361
|
-
shipping_address: { street: "123 Main St" } # Missing city
|
362
|
-
)
|
363
|
-
result.failed? # → true
|
364
|
-
result.metadata
|
365
|
-
# {
|
366
|
-
# reason: "city is required.",
|
367
|
-
# messages: {
|
368
|
-
# city: ["is required"]
|
369
|
-
# }
|
370
|
-
# }
|
371
|
-
```
|
372
|
-
|
373
|
-
### Source Resolution Errors
|
374
|
-
|
375
|
-
```ruby
|
376
|
-
class SourceErrorTask < CMDx::Task
|
377
|
-
required :name, source: :user
|
378
|
-
required :status, source: :nonexistent_method
|
379
|
-
|
380
|
-
def call
|
381
|
-
# Task logic
|
382
|
-
end
|
383
|
-
|
384
|
-
private
|
385
|
-
|
386
|
-
def user
|
387
|
-
# This will raise an error
|
388
|
-
raise StandardError, "User service unavailable"
|
389
|
-
end
|
390
|
-
end
|
391
|
-
|
392
|
-
result = SourceErrorTask.call
|
393
|
-
result.failed? # → true
|
394
|
-
# Error propagated from source resolution failure
|
395
|
-
```
|
396
|
-
|
397
|
-
### Complex Validation Errors
|
398
|
-
|
399
|
-
```ruby
|
400
|
-
class ValidationErrorTask < CMDx::Task
|
401
|
-
required :email, format: { with: /@/ }
|
402
|
-
required :age, type: :integer, numeric: { min: 18, max: 120 }
|
403
|
-
optional :phone, format: { with: /\A\d{10}\z/ }
|
404
|
-
|
405
|
-
required :preferences do
|
406
|
-
required :theme, inclusion: { in: %w[light dark] }
|
407
|
-
optional :language, inclusion: { in: %w[en es fr] }
|
408
|
-
end
|
409
|
-
|
410
|
-
def call
|
411
|
-
# Task logic
|
412
|
-
end
|
413
|
-
end
|
414
|
-
|
415
|
-
# Multiple validation failures
|
416
|
-
result = ValidationErrorTask.call(
|
417
|
-
email: "invalid-email",
|
418
|
-
age: "not-a-number",
|
419
|
-
phone: "123",
|
420
|
-
preferences: {
|
421
|
-
theme: "purple",
|
422
|
-
language: "invalid"
|
423
|
-
}
|
424
|
-
)
|
425
|
-
|
426
|
-
result.failed? # → true
|
427
|
-
result.metadata
|
428
|
-
# {
|
429
|
-
# reason: "email format is not valid. age could not coerce into an integer. phone format is not valid. theme purple is not included in the list. language invalid is not included in the list.",
|
430
|
-
# messages: {
|
431
|
-
# email: ["format is not valid"],
|
432
|
-
# age: ["could not coerce into an integer"],
|
433
|
-
# phone: ["format is not valid"],
|
434
|
-
# theme: ["purple is not included in the list"],
|
435
|
-
# language: ["invalid is not included in the list"]
|
436
|
-
# }
|
437
|
-
# }
|
438
|
-
```
|
439
|
-
|
440
|
-
> [!TIP]
|
441
|
-
> Parameter validation occurs before the `call` method executes, so you can rely on parameter presence and types within your task logic.
|
442
|
-
|
443
|
-
---
|
444
|
-
|
445
|
-
- **Prev:** [Configuration](../configuration.md)
|
446
|
-
- **Next:** [Parameters - Namespacing](namespacing.md)
|