decouplio 1.0.0alpha

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.
Files changed (136) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +53 -0
  3. data/.dockerignore +12 -0
  4. data/.gitignore +13 -0
  5. data/.rspec +3 -0
  6. data/.rubocop.yml +106 -0
  7. data/.rubocop_todo.yml +147 -0
  8. data/.ruby-version +1 -0
  9. data/.vscode/settings.json +3 -0
  10. data/Dockerfile +12 -0
  11. data/Gemfile +8 -0
  12. data/LICENSE +21 -0
  13. data/LICENSE.txt +21 -0
  14. data/README.md +29 -0
  15. data/Rakefile +8 -0
  16. data/benchmarks/.ruby-version +1 -0
  17. data/benchmarks/Dockerfile +12 -0
  18. data/benchmarks/Gemfile +11 -0
  19. data/benchmarks/benchmarks.rb +527 -0
  20. data/bin/console +15 -0
  21. data/bin/setup +8 -0
  22. data/decouplio.gemspec +40 -0
  23. data/docker-compose.yml +18 -0
  24. data/docs/_config.yml +1 -0
  25. data/docs/benchmarks.md +1 -0
  26. data/docs/context.md +74 -0
  27. data/docs/context.rb +62 -0
  28. data/docs/doby.md +80 -0
  29. data/docs/doby.rb +38 -0
  30. data/docs/error_store.md +347 -0
  31. data/docs/error_store.rb +202 -0
  32. data/docs/fail.md +1016 -0
  33. data/docs/fail.rb +762 -0
  34. data/docs/index.md +25 -0
  35. data/docs/inner_action.md +63 -0
  36. data/docs/inner_action.rb +43 -0
  37. data/docs/logic_block.md +25 -0
  38. data/docs/octo.md +269 -0
  39. data/docs/octo.rb +164 -0
  40. data/docs/pass.md +309 -0
  41. data/docs/pass.rb +213 -0
  42. data/docs/quick_start.md +71 -0
  43. data/docs/quick_start.rb +38 -0
  44. data/docs/resq.md +263 -0
  45. data/docs/resq.rb +176 -0
  46. data/docs/step.md +737 -0
  47. data/docs/step.rb +526 -0
  48. data/docs/step_as_a_service.md +109 -0
  49. data/docs/step_as_a_service.rb +77 -0
  50. data/docs/wrap.md +232 -0
  51. data/docs/wrap.rb +137 -0
  52. data/lib/decouplio/action.rb +111 -0
  53. data/lib/decouplio/composer.rb +599 -0
  54. data/lib/decouplio/const/colors.rb +25 -0
  55. data/lib/decouplio/const/reserved_methods.rb +18 -0
  56. data/lib/decouplio/const/results.rb +13 -0
  57. data/lib/decouplio/const/types.rb +173 -0
  58. data/lib/decouplio/const/validations/action_option_class.rb +17 -0
  59. data/lib/decouplio/const/validations/common.rb +14 -0
  60. data/lib/decouplio/const/validations/fail.rb +34 -0
  61. data/lib/decouplio/const/validations/logic.rb +15 -0
  62. data/lib/decouplio/const/validations/octo.rb +44 -0
  63. data/lib/decouplio/const/validations/palp.rb +20 -0
  64. data/lib/decouplio/const/validations/pass.rb +32 -0
  65. data/lib/decouplio/const/validations/resq.rb +67 -0
  66. data/lib/decouplio/const/validations/step.rb +35 -0
  67. data/lib/decouplio/const/validations/wrap.rb +41 -0
  68. data/lib/decouplio/default_error_handler.rb +24 -0
  69. data/lib/decouplio/errors/action_class_error.rb +26 -0
  70. data/lib/decouplio/errors/base_error.rb +30 -0
  71. data/lib/decouplio/errors/error_store_error.rb +17 -0
  72. data/lib/decouplio/errors/extra_key_for_fail_error.rb +26 -0
  73. data/lib/decouplio/errors/extra_key_for_octo_error.rb +26 -0
  74. data/lib/decouplio/errors/extra_key_for_pass_error.rb +26 -0
  75. data/lib/decouplio/errors/extra_key_for_resq_error.rb +29 -0
  76. data/lib/decouplio/errors/extra_key_for_step_error.rb +23 -0
  77. data/lib/decouplio/errors/extra_key_for_wrap_error.rb +23 -0
  78. data/lib/decouplio/errors/fail_controversial_keys_error.rb +26 -0
  79. data/lib/decouplio/errors/fail_finish_him_error.rb +26 -0
  80. data/lib/decouplio/errors/fail_is_first_step_error.rb +18 -0
  81. data/lib/decouplio/errors/invalid_error_class_error.rb +29 -0
  82. data/lib/decouplio/errors/invalid_wrap_name_error.rb +23 -0
  83. data/lib/decouplio/errors/logic_is_not_defined_error.rb +23 -0
  84. data/lib/decouplio/errors/logic_redefinition_error.rb +23 -0
  85. data/lib/decouplio/errors/octo_block_is_not_defined_error.rb +18 -0
  86. data/lib/decouplio/errors/octo_controversial_keys_error.rb +26 -0
  87. data/lib/decouplio/errors/options_validation_error.rb +7 -0
  88. data/lib/decouplio/errors/palp_block_is_not_defined_error.rb +18 -0
  89. data/lib/decouplio/errors/palp_is_not_defined_error.rb +26 -0
  90. data/lib/decouplio/errors/palp_validation_error.rb +21 -0
  91. data/lib/decouplio/errors/pass_controversial_keys_error.rb +26 -0
  92. data/lib/decouplio/errors/pass_finish_him_error.rb +26 -0
  93. data/lib/decouplio/errors/required_options_is_missing_for_octo_error.rb +25 -0
  94. data/lib/decouplio/errors/resq_definition_error.rb +21 -0
  95. data/lib/decouplio/errors/resq_error_class_error.rb +29 -0
  96. data/lib/decouplio/errors/resq_handler_method_error.rb +26 -0
  97. data/lib/decouplio/errors/step_controversial_keys_error.rb +26 -0
  98. data/lib/decouplio/errors/step_finish_him_error.rb +26 -0
  99. data/lib/decouplio/errors/step_is_not_defined_for_fail_error.rb +26 -0
  100. data/lib/decouplio/errors/step_is_not_defined_for_step_error.rb +27 -0
  101. data/lib/decouplio/errors/step_is_not_defined_for_wrap_error.rb +26 -0
  102. data/lib/decouplio/errors/step_name_error.rb +20 -0
  103. data/lib/decouplio/errors/wrap_block_is_not_defined_error.rb +18 -0
  104. data/lib/decouplio/errors/wrap_controversial_keys_error.rb +26 -0
  105. data/lib/decouplio/errors/wrap_finish_him_error.rb +26 -0
  106. data/lib/decouplio/errors/wrap_klass_method_error.rb +23 -0
  107. data/lib/decouplio/flow.rb +17 -0
  108. data/lib/decouplio/logic_dsl.rb +96 -0
  109. data/lib/decouplio/octo_hash_case.rb +31 -0
  110. data/lib/decouplio/octo_options_validator.rb +89 -0
  111. data/lib/decouplio/options_validator.rb +566 -0
  112. data/lib/decouplio/processor.rb +20 -0
  113. data/lib/decouplio/steps/base_resq.rb +31 -0
  114. data/lib/decouplio/steps/base_step.rb +16 -0
  115. data/lib/decouplio/steps/doby.rb +32 -0
  116. data/lib/decouplio/steps/fail.rb +50 -0
  117. data/lib/decouplio/steps/if_condition_fail.rb +28 -0
  118. data/lib/decouplio/steps/if_condition_pass.rb +26 -0
  119. data/lib/decouplio/steps/inner_action_fail.rb +55 -0
  120. data/lib/decouplio/steps/inner_action_pass.rb +38 -0
  121. data/lib/decouplio/steps/inner_action_step.rb +51 -0
  122. data/lib/decouplio/steps/octo.rb +22 -0
  123. data/lib/decouplio/steps/pass.rb +35 -0
  124. data/lib/decouplio/steps/resq_fail.rb +10 -0
  125. data/lib/decouplio/steps/resq_pass.rb +10 -0
  126. data/lib/decouplio/steps/service_fail.rb +51 -0
  127. data/lib/decouplio/steps/service_pass.rb +36 -0
  128. data/lib/decouplio/steps/service_step.rb +47 -0
  129. data/lib/decouplio/steps/step.rb +43 -0
  130. data/lib/decouplio/steps/unless_condition_fail.rb +28 -0
  131. data/lib/decouplio/steps/unless_condition_pass.rb +26 -0
  132. data/lib/decouplio/steps/wrap.rb +62 -0
  133. data/lib/decouplio/validators/condition.rb +49 -0
  134. data/lib/decouplio/version.rb +5 -0
  135. data/lib/decouplio.rb +7 -0
  136. metadata +266 -0
data/docs/fail.md ADDED
@@ -0,0 +1,1016 @@
1
+ # Fail
2
+
3
+ `fail` is the special type of step to mark failure track
4
+
5
+ ## Signature
6
+
7
+ ```ruby
8
+ fail(step_name, **options)
9
+ ```
10
+
11
+ ## Behavior
12
+
13
+ - when step method(`#fail_one`) returns truthy or falsy value then it goes to failure track(`step_two` step) if `on_success:` or `on_failure:` option wasn't passed(see `on_success, on_failure` docs)
14
+
15
+ <details><summary><b>EXAMPLE (CLICK ME)</b></summary>
16
+ <p>
17
+
18
+ ```ruby
19
+ require 'decouplio'
20
+
21
+ class SomeAction < Decouplio::Action
22
+ logic do
23
+ step :step_one
24
+ fail :fail_one
25
+ fail :fail_two
26
+ end
27
+
28
+ def step_one(param_for_step_one:, **)
29
+ param_for_step_one
30
+ end
31
+
32
+ def fail_one(**)
33
+ ctx[:action_failed] = true
34
+ end
35
+
36
+ def fail_two(**)
37
+ ctx[:fail_two] = 'Failure'
38
+ end
39
+ end
40
+
41
+ success_action = SomeAction.call(param_for_step_one: true)
42
+ failure_action = SomeAction.call(param_for_step_one: false)
43
+
44
+ success_action # =>
45
+ # Result: success
46
+
47
+ # Railway Flow:
48
+ # step_one
49
+
50
+ # Context:
51
+ # {:param_for_step_one=>true}
52
+
53
+ # Errors:
54
+ # {}
55
+
56
+
57
+ failure_action # =>
58
+ # Result: failure
59
+
60
+ # Railway Flow:
61
+ # step_one -> fail_one -> fail_two
62
+
63
+ # Context:
64
+ # {:param_for_step_one=>false, :action_failed=>true, :fail_two=>"Failure"}
65
+
66
+ # Errors:
67
+ # {}
68
+ ```
69
+
70
+ ```mermaid
71
+ flowchart LR
72
+ 1(start)-->2(step_one);
73
+ 2(step_one)-->|success track|3(finish_success);
74
+ 2(step_one)-->|failure track|4(fail_one);
75
+ 4(fail_one)-->|failure track|5(fail_two);
76
+ 5(fail_two)-->|failure track|F(finish_failure);
77
+ ```
78
+
79
+ </p>
80
+ </details>
81
+
82
+ ***
83
+
84
+ ## Options
85
+
86
+ ### on_success:
87
+ |Allowed values|Description|
88
+ |-|-|
89
+ |:finish_him|action stops execution if `fail` method returns truthy value|
90
+ |symbol with next step name|step with specified symbol name performs if step method returns truthy value|
91
+
92
+ ### on_success: :finish_him
93
+
94
+ <details><summary><b>EXAMPLE (CLICK ME)</b></summary>
95
+ <p>
96
+
97
+ ```ruby
98
+ require 'decouplio'
99
+
100
+ class SomeActionOnSuccessFinishHim < Decouplio::Action
101
+ logic do
102
+ step :step_one
103
+ fail :fail_one, on_success: :finish_him
104
+ fail :fail_two
105
+ end
106
+
107
+ def step_one(param_for_step_one:, **)
108
+ param_for_step_one
109
+ end
110
+
111
+ def fail_one(fail_one_param:, **)
112
+ ctx[:action_failed] = fail_one_param
113
+ end
114
+
115
+ def fail_two(**)
116
+ ctx[:fail_two] = 'Failure'
117
+ end
118
+ end
119
+
120
+ success_action = SomeActionOnSuccessFinishHim.call(
121
+ param_for_step_one: true
122
+ )
123
+ fail_step_success = SomeActionOnSuccessFinishHim.call(
124
+ param_for_step_one: false,
125
+ fail_one_param: true
126
+ )
127
+ fail_step_failure = SomeActionOnSuccessFinishHim.call(
128
+ param_for_step_one: false,
129
+ fail_one_param: false
130
+ )
131
+
132
+ success_action # =>
133
+ # Result: success
134
+
135
+ # Railway Flow:
136
+ # step_one
137
+
138
+ # Context:
139
+ # {:param_for_step_one=>true}
140
+
141
+ # Errors:
142
+ # {}
143
+
144
+ fail_step_success # =>
145
+ # Result: failure
146
+
147
+ # Railway Flow:
148
+ # step_one -> fail_one
149
+
150
+ # Context:
151
+ # {:param_for_step_one=>false, :fail_one_param=>true, :action_failed=>true}
152
+
153
+ # Errors:
154
+ # {}
155
+
156
+ fail_step_failure # =>
157
+ # Result: failure
158
+
159
+ # Railway Flow:
160
+ # step_one -> fail_one -> fail_two
161
+
162
+ # Context:
163
+ # {:param_for_step_one=>false, :fail_one_param=>false, :action_failed=>false, :fail_two=>"Failure"}
164
+
165
+ # Errors:
166
+ # {}
167
+ ```
168
+
169
+ ```mermaid
170
+ flowchart LR
171
+ 1(start)-->2(step_one);
172
+ 2(step_one)-->|success track|3(finish_success);
173
+ 2(step_one)-->|failure track|4(fail_one success);
174
+ 2(step_one)-->|failure track|7(fail_one failure);
175
+ 4(fail_one success)-->|failure track|5(finish_failure);
176
+ 7(fail_one failure)-->|failure track|6(fail_two);
177
+ 6(fail_two)-->|failure track|5(finish_failure);
178
+ ```
179
+ </p>
180
+ </details>
181
+
182
+ ***
183
+
184
+ ### on_success: next success track step
185
+
186
+ <details><summary><b>EXAMPLE (CLICK ME)</b></summary>
187
+ <p>
188
+
189
+ ```ruby
190
+ require 'decouplio'
191
+
192
+ class SomeActionOnSuccessToSuccessTrack < Decouplio::Action
193
+ logic do
194
+ step :step_one
195
+ fail :fail_one, on_success: :step_two
196
+ step :step_two
197
+ fail :fail_two
198
+ end
199
+
200
+ def step_one(param_for_step_one:, **)
201
+ param_for_step_one
202
+ end
203
+
204
+ def fail_one(fail_one_param:, **)
205
+ ctx[:action_failed] = fail_one_param
206
+ end
207
+
208
+ def step_two(**)
209
+ ctx[:step_two] = 'Success'
210
+ end
211
+
212
+ def fail_two(**)
213
+ ctx[:fail_two] = 'Failure'
214
+ end
215
+ end
216
+
217
+ success_action = SomeActionOnSuccessToSuccessTrack.call(
218
+ param_for_step_one: true
219
+ )
220
+ fail_step_success = SomeActionOnSuccessToSuccessTrack.call(
221
+ param_for_step_one: false,
222
+ fail_one_param: true
223
+ )
224
+ fail_step_failure = SomeActionOnSuccessToSuccessTrack.call(
225
+ param_for_step_one: false,
226
+ fail_one_param: false
227
+ )
228
+
229
+ success_action # =>
230
+ # Result: success
231
+
232
+ # Railway Flow:
233
+ # step_one -> step_two
234
+
235
+ # Context:
236
+ # {:param_for_step_one=>true, :step_two=>"Success"}
237
+
238
+ # Errors:
239
+ # {}
240
+
241
+ fail_step_success # =>
242
+ # Result: success
243
+
244
+ # Railway Flow:
245
+ # step_one -> fail_one -> step_two
246
+
247
+ # Context:
248
+ # {:param_for_step_one=>false, :fail_one_param=>true, :action_failed=>true, :step_two=>"Success"}
249
+
250
+ # Errors:
251
+ # {}
252
+
253
+ fail_step_failure # =>
254
+ # Result: failure
255
+
256
+ # Railway Flow:
257
+ # step_one -> fail_one -> fail_two
258
+
259
+ # Context:
260
+ # {:param_for_step_one=>false, :fail_one_param=>false, :action_failed=>false, :fail_two=>"Failure"}
261
+
262
+ # Errors:
263
+ # {}
264
+ ```
265
+
266
+ ```mermaid
267
+ flowchart LR
268
+ 1(start)-->2(step_one);
269
+ 2(step_one)-->|success track|3(step_two);
270
+ 3(step_two)-->|success track|4(finish_success);
271
+ 2(step_one)-->|failure track|5(fail_one success);
272
+ 2(step_one)-->|failure track|6(fail_one failure);
273
+ 5(fail_one success)-->|success track|3(step_two);
274
+ 6(fail_one failure)-->|failure track|7(fail_two);
275
+ 7(fail_two)-->|failure track|8(finish_failure);
276
+ ```
277
+
278
+ </p>
279
+ </details>
280
+
281
+ ***
282
+
283
+ ### on_success: next failure track step
284
+
285
+ <details><summary><b>EXAMPLE (CLICK ME)</b></summary>
286
+ <p>
287
+
288
+ ```ruby
289
+ require 'decouplio'
290
+
291
+ class SomeActionOnSuccessToFailureTrack < Decouplio::Action
292
+ logic do
293
+ step :step_one
294
+ fail :fail_one, on_success: :fail_three
295
+ step :step_two
296
+ fail :fail_two
297
+ fail :fail_three
298
+ end
299
+
300
+ def step_one(param_for_step_one:, **)
301
+ param_for_step_one
302
+ end
303
+
304
+ def fail_one(fail_one_param:, **)
305
+ ctx[:action_failed] = fail_one_param
306
+ end
307
+
308
+ def step_two(**)
309
+ ctx[:step_two] = 'Success'
310
+ end
311
+
312
+ def fail_two(**)
313
+ ctx[:fail_two] = 'Failure'
314
+ end
315
+
316
+ def fail_three(**)
317
+ ctx[:fail_three] = 'Failure'
318
+ end
319
+ end
320
+
321
+ success_action = SomeActionOnSuccessToFailureTrack.call(
322
+ param_for_step_one: true
323
+ )
324
+ fail_step_success = SomeActionOnSuccessToFailureTrack.call(
325
+ param_for_step_one: false,
326
+ fail_one_param: true
327
+ )
328
+ fail_step_failure = SomeActionOnSuccessToFailureTrack.call(
329
+ param_for_step_one: false,
330
+ fail_one_param: false
331
+ )
332
+
333
+ success_action # =>
334
+ # Result: success
335
+
336
+ # Railway Flow:
337
+ # step_one -> step_two
338
+
339
+ # Context:
340
+ # {:param_for_step_one=>true, :step_two=>"Success"}
341
+
342
+ # Errors:
343
+ # {}
344
+
345
+
346
+ fail_step_success # =>
347
+ # Result: failure
348
+
349
+ # Railway Flow:
350
+ # step_one -> fail_one -> fail_three
351
+
352
+ # Context:
353
+ # {:param_for_step_one=>false, :fail_one_param=>true, :action_failed=>true, :fail_three=>"Failure"}
354
+
355
+ # Errors:
356
+ # {}
357
+
358
+
359
+ fail_step_failure # =>
360
+ # Result: failure
361
+
362
+ # Railway Flow:
363
+ # step_one -> fail_one -> fail_two -> fail_three
364
+
365
+ # Context:
366
+ # {:param_for_step_one=>false, :fail_one_param=>false, :action_failed=>false, :fail_two=>"Failure", :fail_three=>"Failure"}
367
+
368
+ # Errors:
369
+ # {}
370
+ ```
371
+
372
+ ```mermaid
373
+ flowchart LR
374
+ 1(start)-->2(step_one);
375
+ 2(step_one)-->|success track|3(step_two);
376
+ 3(step_two)-->|success track|4(finish success);
377
+ 2(step_one)-->|failure track|5(fail_one success);
378
+ 5(fail_one success)-->|failure track|6(fail_three);
379
+ 6(fail_three)-->|failure track|7(finish failure);
380
+ 2(step_one)-->|failure track|8(fail_one failure);
381
+ 8(fail_one failure)-->|failure track|9(fail_two);
382
+ 9(fail_two)-->|failure track|6(fail_three);
383
+ ```
384
+
385
+ </p>
386
+ </details>
387
+
388
+ ***
389
+
390
+ ### on_failure:
391
+ |Allowed values|Description|
392
+ |-|-|
393
+ |:finish_him|action stops execution if `fail` method returns falsy value|
394
+ |symbol with next step name|step with specified symbol name performs if step method returns falsy value|
395
+
396
+ ### on_failure: :finish_him
397
+
398
+ <details><summary><b>EXAMPLE (CLICK ME)</b></summary>
399
+ <p>
400
+
401
+ ```ruby
402
+ require 'decouplio'
403
+
404
+ class SomeActionOnFailureFinishHim < Decouplio::Action
405
+ logic do
406
+ step :step_one
407
+ fail :fail_one, on_failure: :finish_him
408
+ step :step_two
409
+ fail :fail_two
410
+ end
411
+
412
+ def step_one(param_for_step_one:, **)
413
+ param_for_step_one
414
+ end
415
+
416
+ def fail_one(fail_one_param:, **)
417
+ ctx[:action_failed] = fail_one_param
418
+ end
419
+
420
+ def step_two(**)
421
+ ctx[:step_two] = 'Success'
422
+ end
423
+
424
+ def fail_two(**)
425
+ ctx[:fail_two] = 'Failure'
426
+ end
427
+ end
428
+
429
+ success_action = SomeActionOnFailureFinishHim.call(
430
+ param_for_step_one: true
431
+ )
432
+ fail_step_success = SomeActionOnFailureFinishHim.call(
433
+ param_for_step_one: false,
434
+ fail_one_param: true
435
+ )
436
+ fail_step_failure = SomeActionOnFailureFinishHim.call(
437
+ param_for_step_one: false,
438
+ fail_one_param: false
439
+ )
440
+
441
+ success_action # =>
442
+ # Result: success
443
+
444
+ # Railway Flow:
445
+ # step_one -> step_two
446
+
447
+ # Context:
448
+ # {:param_for_step_one=>true, :step_two=>"Success"}
449
+
450
+ # Errors:
451
+ # {}
452
+
453
+
454
+ fail_step_success # =>
455
+ # Result: failure
456
+
457
+ # Railway Flow:
458
+ # step_one -> fail_one -> fail_two
459
+
460
+ # Context:
461
+ # {:param_for_step_one=>false, :fail_one_param=>true, :action_failed=>true, :fail_two=>"Failure"}
462
+
463
+ # Errors:
464
+ # {}
465
+
466
+
467
+ fail_step_failure # =>
468
+ # Result: failure
469
+
470
+ # Railway Flow:
471
+ # step_one -> fail_one
472
+
473
+ # Context:
474
+ # {:param_for_step_one=>false, :fail_one_param=>false, :action_failed=>false}
475
+
476
+ # Errors:
477
+ # {}
478
+ ```
479
+
480
+ ```mermaid
481
+ flowchart LR
482
+ 1(start)-->2(step_one);
483
+ 2(step_one)-->|success track|3(step_two);
484
+ 3(step_two)-->|success track|4(finish_success);
485
+ 2(step_one)-->|failure track|5(fail_one success);
486
+ 5(fail_one success)-->|failure track|6(fail_two);
487
+ 6(fail_two)-->|failure track|7(finish failure);
488
+ 2(step_one)-->|failure track|8(fail_one failure);
489
+ 8(fail_one failure)-->|failure track|7(finish failure);
490
+ ```
491
+ </p>
492
+ </details>
493
+
494
+ ***
495
+
496
+ ### on_failure: next success track step
497
+
498
+ <details><summary><b>EXAMPLE (CLICK ME)</b></summary>
499
+ <p>
500
+
501
+ ```ruby
502
+ require 'decouplio'
503
+
504
+ class SomeActionOnFailureToSuccessTrack < Decouplio::Action
505
+ logic do
506
+ step :step_one
507
+ fail :fail_one, on_failure: :step_two
508
+ step :step_two
509
+ fail :fail_two
510
+ end
511
+
512
+ def step_one(param_for_step_one:, **)
513
+ param_for_step_one
514
+ end
515
+
516
+ def fail_one(fail_one_param:, **)
517
+ ctx[:action_failed] = fail_one_param
518
+ end
519
+
520
+ def step_two(**)
521
+ ctx[:step_two] = 'Success'
522
+ end
523
+
524
+ def fail_two(**)
525
+ ctx[:fail_two] = 'Failure'
526
+ end
527
+ end
528
+
529
+ success_action = SomeActionOnFailureToSuccessTrack.call(
530
+ param_for_step_one: true
531
+ )
532
+ fail_step_success = SomeActionOnFailureToSuccessTrack.call(
533
+ param_for_step_one: false,
534
+ fail_one_param: true
535
+ )
536
+ fail_step_failure = SomeActionOnFailureToSuccessTrack.call(
537
+ param_for_step_one: false,
538
+ fail_one_param: false
539
+ )
540
+
541
+ success_action # =>
542
+ # Result: success
543
+
544
+ # Railway Flow:
545
+ # step_one -> step_two
546
+
547
+ # Context:
548
+ # {:param_for_step_one=>true, :step_two=>"Success"}
549
+
550
+ # Errors:
551
+ # {}
552
+
553
+ fail_step_success # =>
554
+ # Result: failure
555
+
556
+ # Railway Flow:
557
+ # step_one -> fail_one -> fail_two
558
+
559
+ # Context:
560
+ # {:param_for_step_one=>false, :fail_one_param=>true, :action_failed=>true, :fail_two=>"Failure"}
561
+
562
+ # Errors:
563
+ # {}
564
+
565
+
566
+ fail_step_failure # =>
567
+ # Result: success
568
+
569
+ # Railway Flow:
570
+ # step_one -> fail_one -> step_two
571
+
572
+ # Context:
573
+ # {:param_for_step_one=>false, :fail_one_param=>false, :action_failed=>false, :step_two=>"Success"}
574
+
575
+ # Errors:
576
+ # {}
577
+ ```
578
+
579
+ ```mermaid
580
+ flowchart LR
581
+ 1(start)-->2(step_one);
582
+ 2(step_one)-->|success track|3(finish success);
583
+ 2(step_one)-->|failure track|4(fail_one success);
584
+ 4(fail_one success)-->|failure track|5(fail_two);
585
+ 3(step_two)-->|success track|4(step_three);
586
+ 4(step_three)-->|success track|5(finish_success);
587
+ 2(step_one)-->|failure track|4(step_three);
588
+ ```
589
+ </p>
590
+ </details>
591
+
592
+ ***
593
+
594
+ ### on_failure: next failure track step
595
+
596
+ <details><summary><b>EXAMPLE (CLICK ME)</b></summary>
597
+ <p>
598
+
599
+ ```ruby
600
+ require 'decouplio'
601
+
602
+ class SomeActionOnFailureToFailureTrack < Decouplio::Action
603
+ logic do
604
+ step :step_one
605
+ fail :fail_one, on_failure: :fail_three
606
+ step :step_two
607
+ fail :fail_two
608
+ fail :fail_three
609
+ end
610
+
611
+ def step_one(param_for_step_one:, **)
612
+ param_for_step_one
613
+ end
614
+
615
+ def fail_one(fail_one_param:, **)
616
+ ctx[:action_failed] = fail_one_param
617
+ end
618
+
619
+ def step_two(**)
620
+ ctx[:step_two] = 'Success'
621
+ end
622
+
623
+ def fail_two(**)
624
+ ctx[:fail_two] = 'Failure'
625
+ end
626
+
627
+ def fail_three(**)
628
+ ctx[:fail_three] = 'Failure'
629
+ end
630
+ end
631
+
632
+ success_action = SomeActionOnFailureToFailureTrack.call(
633
+ param_for_step_one: true
634
+ )
635
+ fail_step_success = SomeActionOnFailureToFailureTrack.call(
636
+ param_for_step_one: false,
637
+ fail_one_param: true
638
+ )
639
+ fail_step_failure = SomeActionOnFailureToFailureTrack.call(
640
+ param_for_step_one: false,
641
+ fail_one_param: false
642
+ )
643
+
644
+ success_action # =>
645
+ # Result: success
646
+
647
+ # Railway Flow:
648
+ # step_one -> step_two
649
+
650
+ # Context:
651
+ # {:param_for_step_one=>true, :step_two=>"Success"}
652
+
653
+ # Errors:
654
+ # {}
655
+ fail_step_success # =>
656
+ # Result: failure
657
+
658
+ # Railway Flow:
659
+ # step_one -> fail_one -> fail_two -> fail_three
660
+
661
+ # Context:
662
+ # {:param_for_step_one=>false, :fail_one_param=>true, :action_failed=>true, :fail_two=>"Failure", :fail_three=>"Failure"}
663
+
664
+ # Errors:
665
+ # {}
666
+ fail_step_failure # =>
667
+ # Result: failure
668
+
669
+ # Railway Flow:
670
+ # step_one -> fail_one -> fail_three
671
+
672
+ # Context:
673
+ # {:param_for_step_one=>false, :fail_one_param=>false, :action_failed=>false, :fail_three=>"Failure"}
674
+
675
+ # Errors:
676
+ # {}
677
+ ```
678
+
679
+ ```mermaid
680
+ flowchart LR
681
+ 1(start)-->2(step_one);
682
+ 2(step_one)-->|success track|3(step_two);
683
+ 3(step_two)-->|success track|4(finish_success);
684
+ 2(step_one)-->|failure track|5(fail_one success);
685
+ 5(fail_one success)-->|failure track|6(fail_two);
686
+ 6(fail_two)-->|failure track|7(fail_three);
687
+ 7(fail_three)-->|failure track|8(finish failure);
688
+ 2(step_one)-->|failure track|9(fail_one failure);
689
+ 9(fail_one failure)-->|failure track|7(fail_three);
690
+ ```
691
+ </p>
692
+ </details>
693
+
694
+ ***
695
+
696
+ ### if: condition method name
697
+ Can be used in case if for some reason step shouldn't be executed
698
+
699
+ <details><summary><b>EXAMPLE (CLICK ME)</b></summary>
700
+ <p>
701
+
702
+ ```ruby
703
+ require 'decouplio'
704
+
705
+ class SomeActionOnIfCondition < Decouplio::Action
706
+ logic do
707
+ step :step_one
708
+ fail :fail_one
709
+ step :step_two
710
+ fail :fail_two, if: :some_condition?
711
+ fail :fail_three
712
+ end
713
+
714
+ def step_one(param_for_step_one:, **)
715
+ param_for_step_one
716
+ end
717
+
718
+ def fail_one(**)
719
+ ctx[:action_failed] = true
720
+ end
721
+
722
+ def step_two(**)
723
+ ctx[:step_two] = 'Success'
724
+ end
725
+
726
+ def fail_two(**)
727
+ ctx[:fail_two] = 'Failure'
728
+ end
729
+
730
+ def fail_three(**)
731
+ ctx[:fail_three] = 'Failure'
732
+ end
733
+
734
+ def some_condition?(if_condition_param:, **)
735
+ if_condition_param
736
+ end
737
+ end
738
+
739
+ success_action = SomeActionOnIfCondition.call(
740
+ param_for_step_one: true
741
+ )
742
+ fail_condition_positive = SomeActionOnIfCondition.call(
743
+ param_for_step_one: false,
744
+ if_condition_param: true
745
+ )
746
+ fail_condition_negative = SomeActionOnIfCondition.call(
747
+ param_for_step_one: false,
748
+ if_condition_param: false
749
+ )
750
+
751
+ success_action # =>
752
+ # Result: success
753
+
754
+ # Railway Flow:
755
+ # step_one -> step_two
756
+
757
+ # Context:
758
+ # {:param_for_step_one=>true, :step_two=>"Success"}
759
+
760
+ # Errors:
761
+ # {}
762
+
763
+ fail_condition_positive # =>
764
+ # Result: failure
765
+
766
+ # Railway Flow:
767
+ # step_one -> fail_one -> fail_two -> fail_three
768
+
769
+ # Context:
770
+ # {:param_for_step_one=>false, :if_condition_param=>true, :action_failed=>true, :fail_two=>"Failure", :fail_three=>"Failure"}
771
+
772
+ # Errors:
773
+ # {}
774
+
775
+ fail_condition_negative # =>
776
+ # Result: failure
777
+
778
+ # Railway Flow:
779
+ # step_one -> fail_one -> fail_three
780
+
781
+ # Context:
782
+ # {:param_for_step_one=>false, :if_condition_param=>false, :action_failed=>true, :fail_three=>"Failure"}
783
+
784
+ # Errors:
785
+ # {}
786
+ ```
787
+
788
+ ```mermaid
789
+ flowchart LR
790
+ 1(start)-->2(step_one);
791
+ 2(step_one)-->|success tack|3(step_two);
792
+ 3(step_two)-->|success track|4(finish_success);
793
+ 2(step_one)-->|failure track|5(fail_one);
794
+ 5(fail_one)-->|condition positive|6(fail_two);
795
+ 6(fail_two)-->|failure track|7(fail_three);
796
+ 5(fail_one)-->|condition negative|7(fail_three);
797
+ 7(fail_three)-->|failure track|8(finish failure);
798
+ ```
799
+ </p>
800
+ </details>
801
+
802
+ ***
803
+
804
+ ### unless: condition method name
805
+ Can be used in case if for some reason step shouldn't be executed
806
+
807
+ <details><summary><b>EXAMPLE (CLICK ME)</b></summary>
808
+ <p>
809
+
810
+ ```ruby
811
+ require 'decouplio'
812
+
813
+ class SomeActionOnUnlessCondition < Decouplio::Action
814
+ logic do
815
+ step :step_one
816
+ fail :fail_one
817
+ step :step_two
818
+ fail :fail_two, unless: :some_condition?
819
+ fail :fail_three
820
+ end
821
+
822
+ def step_one(param_for_step_one:, **)
823
+ param_for_step_one
824
+ end
825
+
826
+ def fail_one(**)
827
+ ctx[:action_failed] = true
828
+ end
829
+
830
+ def step_two(**)
831
+ ctx[:step_two] = 'Success'
832
+ end
833
+
834
+ def fail_two(**)
835
+ ctx[:fail_two] = 'Failure'
836
+ end
837
+
838
+ def fail_three(**)
839
+ ctx[:fail_three] = 'Failure'
840
+ end
841
+
842
+ def some_condition?(if_condition_param:, **)
843
+ if_condition_param
844
+ end
845
+ end
846
+
847
+ success_action = SomeActionOnUnlessCondition.call(
848
+ param_for_step_one: true
849
+ )
850
+ fail_condition_positive = SomeActionOnUnlessCondition.call(
851
+ param_for_step_one: false,
852
+ if_condition_param: false
853
+ )
854
+ fail_condition_negative = SomeActionOnUnlessCondition.call(
855
+ param_for_step_one: false,
856
+ if_condition_param: true
857
+ )
858
+
859
+ success_action # =>
860
+ # Result: success
861
+
862
+ # Railway Flow:
863
+ # step_one -> step_two
864
+
865
+ # Context:
866
+ # {:param_for_step_one=>true, :step_two=>"Success"}
867
+
868
+ # Errors:
869
+ # {}
870
+
871
+ fail_condition_positive # =>
872
+ # Result: failure
873
+
874
+ # Railway Flow:
875
+ # step_one -> fail_one -> fail_two -> fail_three
876
+
877
+ # Context:
878
+ # {:param_for_step_one=>false, :if_condition_param=>false, :action_failed=>true, :fail_two=>"Failure", :fail_three=>"Failure"}
879
+
880
+ # Errors:
881
+ # {}
882
+
883
+ fail_condition_negative # =>
884
+ # Result: failure
885
+
886
+ # Railway Flow:
887
+ # step_one -> fail_one -> fail_three
888
+
889
+ # Context:
890
+ # {:param_for_step_one=>false, :if_condition_param=>true, :action_failed=>true, :fail_three=>"Failure"}
891
+
892
+ # Errors:
893
+ # {}
894
+ ```
895
+
896
+
897
+ ```mermaid
898
+ flowchart LR
899
+ 1(start)-->2(step_one);
900
+ 2(step_one)-->|success tack|3(step_two);
901
+ 3(step_two)-->|success track|4(finish_success);
902
+ 2(step_one)-->|failure track|5(fail_one);
903
+ 5(fail_one)-->|condition positive|6(fail_two);
904
+ 6(fail_two)-->|failure track|7(fail_three);
905
+ 5(fail_one)-->|condition negative|7(fail_three);
906
+ 7(fail_three)-->|failure track|8(finish failure);
907
+ ```
908
+ </p>
909
+ </details>
910
+
911
+ ***
912
+
913
+ ### finish_him: :on_success
914
+ The same behavior as for `on_success: :finish_him`
915
+
916
+ ### finish_him: :on_failure
917
+ The same behavior as for `on_failure: :finish_him`
918
+
919
+ ### finish_him: true
920
+ Will finish action execution anyway
921
+
922
+ <details><summary><b>EXAMPLE (CLICK ME)</b></summary>
923
+ <p>
924
+
925
+ ```ruby
926
+ require 'decouplio'
927
+
928
+ class SomeActionFinishHimTrue < Decouplio::Action
929
+ logic do
930
+ step :step_one
931
+ fail :fail_one, finish_him: true
932
+ step :step_two
933
+ fail :fail_two
934
+ end
935
+
936
+ def step_one(param_for_step_one:, **)
937
+ param_for_step_one
938
+ end
939
+
940
+ def fail_one(fail_one_param:, **)
941
+ ctx[:action_failed] = fail_one_param
942
+ end
943
+
944
+ def step_two(**)
945
+ ctx[:step_two] = 'Success'
946
+ end
947
+
948
+ def fail_two(**)
949
+ ctx[:fail_two] = 'Failure'
950
+ end
951
+ end
952
+
953
+ success_action = SomeActionFinishHimTrue.call(
954
+ param_for_step_one: true
955
+ )
956
+ fail_step_success = SomeActionFinishHimTrue.call(
957
+ param_for_step_one: false,
958
+ fail_one_param: true
959
+ )
960
+ fail_step_failure = SomeActionFinishHimTrue.call(
961
+ param_for_step_one: false,
962
+ fail_one_param: false
963
+ )
964
+
965
+ success_action # =>
966
+ # Result: success
967
+
968
+ # Railway Flow:
969
+ # step_one -> step_two
970
+
971
+ # Context:
972
+ # {:param_for_step_one=>true, :step_two=>"Success"}
973
+
974
+ # Errors:
975
+ # {}
976
+
977
+ fail_step_success # =>
978
+ # Result: failure
979
+
980
+ # Railway Flow:
981
+ # step_one -> fail_one
982
+
983
+ # Context:
984
+ # {:param_for_step_one=>false, :fail_one_param=>true, :action_failed=>true}
985
+
986
+ # Errors:
987
+ # {}
988
+
989
+ fail_step_failure # =>
990
+ # Result: failure
991
+
992
+ # Railway Flow:
993
+ # step_one -> fail_one
994
+
995
+ # Context:
996
+ # {:param_for_step_one=>false, :fail_one_param=>false, :action_failed=>false}
997
+
998
+ # Errors:
999
+ # {}
1000
+ ```
1001
+
1002
+
1003
+ ```mermaid
1004
+ flowchart LR
1005
+ 1(start)-->2(step_one);
1006
+ 2(step_one)-->|success tack|3(step_two);
1007
+ 3(step_two)-->|success track|4(finish_success);
1008
+ 2(step_one)-->|failure track|5(fail_one success);
1009
+ 5(fail_one success)-->|failure track|6(finish failure);
1010
+ 2(step_one)-->|failure track|7(fail_one failure);
1011
+ 7(fail_one failure)-->|failure track|6(finish failure);
1012
+ ```
1013
+ </p>
1014
+ </details>
1015
+
1016
+ ***