decouplio 1.0.0alpha1 → 1.0.0alpha2

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -0
  3. data/README.md +26 -2
  4. data/benchmarks/Gemfile +2 -1
  5. data/benchmarks/multi_step_benchmark.rb +335 -0
  6. data/benchmarks/single_step_benchmark.rb +159 -0
  7. data/docker-compose.yml +13 -2
  8. data/docs/deny.rb +59 -0
  9. data/docs/doby.rb +1 -1
  10. data/docs/doby_deny.md +171 -0
  11. data/docs/fail.md +143 -0
  12. data/docs/fail.rb +126 -29
  13. data/docs/resq.md +2 -2
  14. data/docs/step.md +148 -0
  15. data/docs/step.rb +119 -18
  16. data/docs/step_as_a_service.md +25 -11
  17. data/docs/step_as_a_service.rb +2 -2
  18. data/docs/wrap.md +8 -0
  19. data/lib/decouplio/action.rb +22 -3
  20. data/lib/decouplio/composer.rb +78 -12
  21. data/lib/decouplio/const/reserved_methods.rb +13 -9
  22. data/lib/decouplio/const/results.rb +2 -0
  23. data/lib/decouplio/const/types.rb +11 -5
  24. data/lib/decouplio/const/validations/deny.rb +11 -0
  25. data/lib/decouplio/const/validations/fail.rb +1 -1
  26. data/lib/decouplio/errors/deny_can_not_be_first_step_error.rb +18 -0
  27. data/lib/decouplio/errors/{fail_is_first_step_error.rb → fail_can_not_be_first_step_error.rb} +1 -1
  28. data/lib/decouplio/logic_dsl.rb +14 -2
  29. data/lib/decouplio/options_validator.rb +8 -3
  30. data/lib/decouplio/steps/deny.rb +31 -0
  31. data/lib/decouplio/steps/doby.rb +5 -1
  32. data/lib/decouplio/steps/fail.rb +7 -22
  33. data/lib/decouplio/steps/inner_action_fail.rb +7 -22
  34. data/lib/decouplio/steps/inner_action_step.rb +7 -18
  35. data/lib/decouplio/steps/service_fail.rb +11 -23
  36. data/lib/decouplio/steps/service_pass.rb +4 -1
  37. data/lib/decouplio/steps/service_step.rb +11 -19
  38. data/lib/decouplio/steps/shared/fail_resolver.rb +40 -0
  39. data/lib/decouplio/steps/shared/step_resolver.rb +43 -0
  40. data/lib/decouplio/steps/step.rb +7 -18
  41. data/lib/decouplio/steps/wrap.rb +7 -18
  42. data/lib/decouplio/version.rb +1 -1
  43. metadata +12 -5
  44. data/benchmarks/benchmarks.rb +0 -527
  45. data/docs/doby.md +0 -80
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 455ba12276135c618f5d53a9ff53bf8d3c7ec8074e387ea4790f2307e344c4ec
4
- data.tar.gz: 126488804cc9391fdb0fe3f9a0d2ac4060fa42bbe1d733af64bec5681e9f890d
3
+ metadata.gz: 1b94378c5ef6384c1e88ea9c71ef987b7a607da12cae8ed05f1ffdcc5c575c3b
4
+ data.tar.gz: 7954e4f1bd9fad05c07be76cbd3b8343477d9f5610751c59840e0b01907b079d
5
5
  SHA512:
6
- metadata.gz: '00912905816c9e9393e907185347ddd3d9fb2de753a2fa3d7aeaae704ef8d93e26ff5f3ae62a7589384921717b9d764af2e2502b7c43866fb503f63837079999'
7
- data.tar.gz: 50d1d117ee1ec34f94f750c1f2d1aad73f41127e8585bd01ee32209b361d067b6fa054b242878e18bfa01682344388badb386dc6a39883a1957516ccfc4a202f
6
+ metadata.gz: 762378c8f56ca4833f79255396a0a09b449767d04be8dbc07f87b66924f90334f6780b63eeca020853a065d5c227f99a6987ec2cb024cfbffccd62326d1b2f36
7
+ data.tar.gz: b233ac1a47544de489e147b2b021d1d98968f85feb8dc780d182147d4db6cb81098240f43b9da2893cba2b4cb1e7a823b07619fb7495dce3fb29d70e6174c1b4
data/.rubocop.yml CHANGED
@@ -104,3 +104,7 @@ RSpec/MultipleMemoizedHelpers:
104
104
  Naming/PredicateName:
105
105
  Exclude:
106
106
  - lib/decouplio/step.rb
107
+
108
+ Naming/MethodParameterName:
109
+ Exclude:
110
+ - spec/support/cases/**/*
data/README.md CHANGED
@@ -14,16 +14,40 @@ And then execute:
14
14
 
15
15
  $ bundle
16
16
 
17
- Or install it yourself as:
17
+ Or install it by yourself:
18
18
 
19
19
  $ gem install decouplio
20
20
 
21
- # [>>>>>>>DOCS HERE<<<<<<<](https://github.com/differencialx/decouplio/blob/master/docs/index.md)
21
+ ## Currently decouplio is in alpha testing, more features will come soon.
22
+
23
+ ### Compatibility
24
+ Ruby:
25
+ - 2.7
26
+ - 3.0
27
+
28
+ ### Docs
29
+
30
+ - [Quick start](https://github.com/differencialx/decouplio/blob/master/docs/quick_start.md)
31
+ - [Logic block](https://github.com/differencialx/decouplio/blob/master/docs/logic_block.md)
32
+ - [Context](https://github.com/differencialx/decouplio/blob/master/docs/context.md)
33
+ - [Step](https://github.com/differencialx/decouplio/blob/master/docs/step.md)
34
+ - [Fail](https://github.com/differencialx/decouplio/blob/master/docs/fail.md)
35
+ - [Pass](https://github.com/differencialx/decouplio/blob/master/docs/pass.md)
36
+ - [Octo](https://github.com/differencialx/decouplio/blob/master/docs/octo.md)
37
+ - [Wrap](https://github.com/differencialx/decouplio/blob/master/docs/wrap.md)
38
+ - [Resq](https://github.com/differencialx/decouplio/blob/master/docs/resq.md)
39
+ - [Inner action](https://github.com/differencialx/decouplio/blob/master/docs/inner_action.md)
40
+ - [Doby/Deny](https://github.com/differencialx/decouplio/blob/master/docs/doby_deny.md)
41
+ - [Step as a service](https://github.com/differencialx/decouplio/blob/master/docs/step_as_a_service.md)
42
+ - [Error store](https://github.com/differencialx/decouplio/blob/master/docs/error_store.md)
43
+ - [Benchmarks](https://github.com/differencialx/decouplio/blob/master/docs/benchmarks.md)
22
44
 
23
45
  ## Contributing
24
46
 
25
47
  Bug reports and pull requests are welcome on GitHub at https://github.com/differencialx/decouplio.
26
48
 
49
+ More detailed description for contribution process will be added later.
50
+
27
51
  ## License
28
52
 
29
53
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/benchmarks/Gemfile CHANGED
@@ -3,7 +3,8 @@
3
3
  source 'https://rubygems.org'
4
4
 
5
5
  gem 'active_interaction', '~> 4.1'
6
- gem 'decouplio', path: '../'
6
+ gem 'benchmark-ips'
7
+ gem 'decouplio'
7
8
  gem 'interactor', '~> 3.0'
8
9
  gem 'mutations'
9
10
  gem 'pry-byebug'
@@ -0,0 +1,335 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_interaction'
4
+ require 'interactor'
5
+ require 'mutations'
6
+ require 'trailblazer'
7
+ require 'decouplio'
8
+ require 'benchmark/ips'
9
+
10
+ class RegularServiceTest
11
+ attr_accessor :ctx, :param1
12
+
13
+ def self.call(param1:)
14
+ new(param1: param1).call
15
+ end
16
+
17
+ def initialize(param1:)
18
+ @param1 = param1
19
+ @ctx = {}
20
+ end
21
+
22
+ def call
23
+ step_one
24
+ step_two
25
+ step_three
26
+ step_four
27
+ step_five
28
+ step_six
29
+ step_seven
30
+ step_eight
31
+ step_nine
32
+ end
33
+
34
+ def step_one
35
+ ctx[:step_one] = param1
36
+ end
37
+
38
+ def step_two
39
+ ctx[:step_two] = ctx[:step_one]
40
+ end
41
+
42
+ def step_three
43
+ ctx[:step_three] = ctx[:step_two]
44
+ end
45
+
46
+ def step_four
47
+ ctx[:step_four] = ctx[:step_three]
48
+ end
49
+
50
+ def step_five
51
+ ctx[:step_five] = ctx[:step_four]
52
+ end
53
+
54
+ def step_six
55
+ ctx[:step_six] = ctx[:step_five]
56
+ end
57
+
58
+ def step_seven
59
+ ctx[:step_seven] = ctx[:step_six]
60
+ end
61
+
62
+ def step_eight
63
+ ctx[:step_eight] = ctx[:step_seven]
64
+ end
65
+
66
+ def step_nine
67
+ ctx[:step_nine] = ctx[:step_eight]
68
+ end
69
+ end
70
+
71
+ class DecouplioTestSeveralSteps < Decouplio::Action
72
+ logic do
73
+ step :step_one
74
+ step :step_two
75
+ step :step_three
76
+ step :step_four
77
+ step :step_five
78
+ step :step_six
79
+ step :step_seven
80
+ step :step_eight
81
+ step :step_nine
82
+ end
83
+
84
+ def step_one(param1:, **)
85
+ ctx[:step_one] = param1
86
+ end
87
+
88
+ def step_two(step_one:, **)
89
+ ctx[:step_two] = step_one
90
+ end
91
+
92
+ def step_three(step_two:, **)
93
+ ctx[:step_three] = step_two
94
+ end
95
+
96
+ def step_four(step_three:, **)
97
+ ctx[:step_four] = step_three
98
+ end
99
+
100
+ def step_five(step_four:, **)
101
+ ctx[:step_five] = step_four
102
+ end
103
+
104
+ def step_six(step_five:, **)
105
+ ctx[:step_six] = step_five
106
+ end
107
+
108
+ def step_seven(step_six:, **)
109
+ ctx[:step_seven] = step_six
110
+ end
111
+
112
+ def step_eight(step_seven:, **)
113
+ ctx[:step_eight] = step_seven
114
+ end
115
+
116
+ def step_nine(step_eight:, **)
117
+ ctx[:step_nine] = step_eight
118
+ end
119
+ end
120
+
121
+ class StepOne
122
+ include Interactor
123
+
124
+ def call
125
+ context.step_one = context.param1
126
+ end
127
+ end
128
+
129
+ class StepTwo
130
+ include Interactor
131
+
132
+ def call
133
+ context.step_two = context.step_one
134
+ end
135
+ end
136
+
137
+ class StepThree
138
+ include Interactor
139
+
140
+ def call
141
+ context.step_three = context.step_two
142
+ end
143
+ end
144
+
145
+ class StepFour
146
+ include Interactor
147
+
148
+ def call
149
+ context.step_four = context.step_three
150
+ end
151
+ end
152
+
153
+ class StepFive
154
+ include Interactor
155
+
156
+ def call
157
+ context.step_five = context.step_four
158
+ end
159
+ end
160
+
161
+ class StepSix
162
+ include Interactor
163
+
164
+ def call
165
+ context.step_six = context.step_five
166
+ end
167
+ end
168
+
169
+ class StepSeven
170
+ include Interactor
171
+
172
+ def call
173
+ context.step_seven = context.step_six
174
+ end
175
+ end
176
+
177
+ class StepEight
178
+ include Interactor
179
+
180
+ def call
181
+ context.step_eight = context.step_seven
182
+ end
183
+ end
184
+
185
+ class StepNine
186
+ include Interactor
187
+
188
+ def call
189
+ context.step_nine = context.step_eight
190
+ end
191
+ end
192
+
193
+ class InteractorTestOrganizer
194
+ include Interactor::Organizer
195
+
196
+ organize StepOne,
197
+ StepTwo,
198
+ StepThree,
199
+ StepFour,
200
+ StepFive,
201
+ StepSix,
202
+ StepSeven,
203
+ StepEight,
204
+ StepNine
205
+ end
206
+
207
+ class TrailblazerTestSeveralSteps < Trailblazer::Activity::Railway
208
+ step :step_one
209
+ step :step_two
210
+ step :step_three
211
+ step :step_four
212
+ step :step_five
213
+ step :step_six
214
+ step :step_seven
215
+ step :step_eight
216
+ step :step_nine
217
+
218
+ def step_one(ctx, param1:, **)
219
+ ctx[:step_one] = param1
220
+ end
221
+
222
+ def step_two(ctx, step_one:, **)
223
+ ctx[:step_two] = step_one
224
+ end
225
+
226
+ def step_three(ctx, step_two:, **)
227
+ ctx[:step_three] = step_two
228
+ end
229
+
230
+ def step_four(ctx, step_three:, **)
231
+ ctx[:step_four] = step_three
232
+ end
233
+
234
+ def step_five(ctx, step_four:, **)
235
+ ctx[:step_five] = step_four
236
+ end
237
+
238
+ def step_six(ctx, step_five:, **)
239
+ ctx[:step_six] = step_five
240
+ end
241
+
242
+ def step_seven(ctx, step_six:, **)
243
+ ctx[:step_seven] = step_six
244
+ end
245
+
246
+ def step_eight(ctx, step_seven:, **)
247
+ ctx[:step_eight] = step_seven
248
+ end
249
+
250
+ def step_nine(ctx, step_eight:, **)
251
+ ctx[:step_nine] = step_eight
252
+ end
253
+ end
254
+
255
+ class DecouplioStepOne
256
+ def self.call(ctx:)
257
+ ctx[:step_one] = ctx[:param1]
258
+ end
259
+ end
260
+
261
+ class DecouplioStepTwo
262
+ def self.call(ctx:)
263
+ ctx[:step_two] = ctx[:step_one]
264
+ end
265
+ end
266
+
267
+ class DecouplioStepThree
268
+ def self.call(ctx:)
269
+ ctx[:step_three] = ctx[:step_two]
270
+ end
271
+ end
272
+
273
+ class DecouplioStepFour
274
+ def self.call(ctx:)
275
+ ctx[:step_four] = ctx[:step_three]
276
+ end
277
+ end
278
+
279
+ class DecouplioStepFive
280
+ def self.call(ctx:)
281
+ ctx[:step_five] = ctx[:step_four]
282
+ end
283
+ end
284
+
285
+ class DecouplioStepSix
286
+ def self.call(ctx:)
287
+ ctx[:step_six] = ctx[:step_five]
288
+ end
289
+ end
290
+
291
+ class DecouplioStepSeven
292
+ def self.call(ctx:)
293
+ ctx[:step_seven] = ctx[:step_six]
294
+ end
295
+ end
296
+
297
+ class DecouplioStepEight
298
+ def self.call(ctx:)
299
+ ctx[:step_eight] = ctx[:step_seven]
300
+ end
301
+ end
302
+
303
+ class DecouplioStepNine
304
+ def self.call(ctx:)
305
+ ctx[:step_nine] = ctx[:step_eight]
306
+ end
307
+ end
308
+
309
+ class DecouplioServiceStepsTest < Decouplio::Action
310
+ logic do
311
+ step DecouplioStepOne
312
+ step DecouplioStepTwo
313
+ step DecouplioStepThree
314
+ step DecouplioStepFour
315
+ step DecouplioStepFive
316
+ step DecouplioStepSix
317
+ step DecouplioStepSeven
318
+ step DecouplioStepEight
319
+ step DecouplioStepNine
320
+ end
321
+ end
322
+
323
+ iteration_count = 100_000_0
324
+
325
+ Benchmark.ips do |x|
326
+ x.report('RegularService') { iteration_count.times { RegularServiceTest.call(param1: 'param1') } }
327
+ x.report('Decouplio several steps') { iteration_count.times { DecouplioTestSeveralSteps.call(param1: 'param1') } }
328
+ x.report('Decouplio service steps') { iteration_count.times { DecouplioServiceStepsTest.call(param1: 'param1') } }
329
+ x.report('Trailblazer several steps') { iteration_count.times { TrailblazerTestSeveralSteps.call(param1: 'param1') } }
330
+ x.report('Interactor several interactions with organizer') do
331
+ iteration_count.times { InteractorTestOrganizer.call(param1: 'param1') }
332
+ end
333
+
334
+ x.compare!
335
+ end
@@ -0,0 +1,159 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_interaction'
4
+ require 'interactor'
5
+ require 'mutations'
6
+ require 'trailblazer'
7
+ require 'decouplio'
8
+ require 'benchmark/ips'
9
+
10
+ class MutationTest < Mutations::Command
11
+ optional do
12
+ string :param1
13
+ end
14
+
15
+ def execute
16
+ @context = {}
17
+ @context[:step_one] = param1
18
+ @context[:step_two] = @context[:step_one]
19
+ @context[:step_three] = @context[:step_two]
20
+ @context[:step_four] = @context[:step_three]
21
+ @context[:step_five] = @context[:step_four]
22
+ @context[:step_six] = @context[:step_five]
23
+ @context[:step_seven] = @context[:step_six]
24
+ @context[:step_eight] = @context[:step_seven]
25
+ @context[:step_nine] = @context[:step_eight]
26
+
27
+ @context
28
+ end
29
+ end
30
+
31
+ class ActiveInteractionTest < ActiveInteraction::Base
32
+ string :param1
33
+
34
+ def execute
35
+ @context = {}
36
+ @context[:step_one] = param1
37
+ @context[:step_two] = @context[:step_one]
38
+ @context[:step_three] = @context[:step_two]
39
+ @context[:step_four] = @context[:step_three]
40
+ @context[:step_five] = @context[:step_four]
41
+ @context[:step_six] = @context[:step_five]
42
+ @context[:step_seven] = @context[:step_six]
43
+ @context[:step_eight] = @context[:step_seven]
44
+ @context[:step_nine] = @context[:step_eight]
45
+
46
+ @context
47
+ end
48
+ end
49
+
50
+ class DecouplioTestOneStep < Decouplio::Action
51
+ logic do
52
+ step :step_one
53
+ end
54
+
55
+ def step_one(param1:, **)
56
+ ctx[:step_one] = param1
57
+ ctx[:step_two] = ctx[:step_one]
58
+ ctx[:step_three] = ctx[:step_two]
59
+ ctx[:step_four] = ctx[:step_three]
60
+ ctx[:step_five] = ctx[:step_four]
61
+ ctx[:step_six] = ctx[:step_five]
62
+ ctx[:step_seven] = ctx[:step_six]
63
+ ctx[:step_eight] = ctx[:step_seven]
64
+ ctx[:step_nine] = ctx[:step_eight]
65
+ end
66
+ end
67
+
68
+ class InteractorWithoutOrganizer
69
+ include Interactor
70
+
71
+ def call
72
+ context.step_one = context.param1
73
+ context.step_two = context.step_one
74
+ context.step_three = context.step_two
75
+ context.step_four = context.step_three
76
+ context.step_five = context.step_four
77
+ context.step_six = context.step_five
78
+ context.step_seven = context.step_six
79
+ context.step_eight = context.step_seven
80
+ context.step_nine = context.step_eight
81
+ end
82
+ end
83
+
84
+ class RegularServiceTest
85
+ attr_accessor :ctx, :param1
86
+
87
+ def self.call(param1:)
88
+ new(param1: param1).call
89
+ end
90
+
91
+ def initialize(param1:)
92
+ @param1 = param1
93
+ @ctx = {}
94
+ end
95
+
96
+ def call
97
+ ctx[:step_one] = param1
98
+ ctx[:step_two] = ctx[:step_one]
99
+ ctx[:step_three] = ctx[:step_two]
100
+ ctx[:step_four] = ctx[:step_three]
101
+ ctx[:step_five] = ctx[:step_four]
102
+ ctx[:step_six] = ctx[:step_five]
103
+ ctx[:step_seven] = ctx[:step_six]
104
+ ctx[:step_eight] = ctx[:step_seven]
105
+ ctx[:step_nine] = ctx[:step_eight]
106
+ end
107
+ end
108
+
109
+ class TrailblazerTestOneStep < Trailblazer::Activity::Railway
110
+ step :step_one
111
+
112
+ def step_one(ctx, param1:, **)
113
+ ctx[:step_one] = param1
114
+ ctx[:step_two] = ctx[:step_one]
115
+ ctx[:step_three] = ctx[:step_two]
116
+ ctx[:step_four] = ctx[:step_three]
117
+ ctx[:step_five] = ctx[:step_four]
118
+ ctx[:step_six] = ctx[:step_five]
119
+ ctx[:step_seven] = ctx[:step_six]
120
+ ctx[:step_eight] = ctx[:step_seven]
121
+ ctx[:step_nine] = ctx[:step_eight]
122
+ end
123
+ end
124
+
125
+ class ServiceAsStep
126
+ def self.call(ctx:)
127
+ ctx[:step_one] = ctx[:param1]
128
+ ctx[:step_two] = ctx[:step_one]
129
+ ctx[:step_three] = ctx[:step_two]
130
+ ctx[:step_four] = ctx[:step_three]
131
+ ctx[:step_five] = ctx[:step_four]
132
+ ctx[:step_six] = ctx[:step_five]
133
+ ctx[:step_seven] = ctx[:step_six]
134
+ ctx[:step_eight] = ctx[:step_seven]
135
+ ctx[:step_nine] = ctx[:step_eight]
136
+ end
137
+ end
138
+
139
+ class DecouplioTestOneStepAsService < Decouplio::Action
140
+ logic do
141
+ step ServiceAsStep
142
+ end
143
+ end
144
+
145
+ iteration_count = 100_000
146
+
147
+ Benchmark.ips do |x|
148
+ x.report('Mutation') { iteration_count.times { MutationTest.run(param1: 'param1') } }
149
+ x.report('ActiveInteraction') { iteration_count.times { ActiveInteractionTest.run(param1: 'param1') } }
150
+ x.report('Trailblazer one step') { iteration_count.times { TrailblazerTestOneStep.call(param1: 'param1') } }
151
+ x.report('Interactor one interactor') { iteration_count.times { InteractorWithoutOrganizer.call(param1: 'param1') } }
152
+ x.report('RegularService') { iteration_count.times { RegularServiceTest.call(param1: 'param1') } }
153
+ x.report('Decouplio one step') { iteration_count.times { DecouplioTestOneStep.call(param1: 'param1') } }
154
+ x.report('Decouplio one step as service') do
155
+ iteration_count.times { DecouplioTestOneStepAsService.call(param1: 'param1') }
156
+ end
157
+
158
+ x.compare!
159
+ end
data/docker-compose.yml CHANGED
@@ -1,11 +1,22 @@
1
1
  version: "3.7"
2
2
 
3
3
  services:
4
- benchmark:
4
+ benchmark_single_step:
5
5
  build:
6
6
  dockerfile: benchmarks/Dockerfile
7
7
  context: .
8
- command: "ruby benchmarks.rb"
8
+ command: "ruby single_step_benchmark.rb"
9
+ deploy:
10
+ resources:
11
+ limits:
12
+ cpus: '1'
13
+ memory: 400M
14
+
15
+ benchmark_multi_step:
16
+ build:
17
+ dockerfile: benchmarks/Dockerfile
18
+ context: .
19
+ command: "ruby multi_step_benchmark.rb"
9
20
  deploy:
10
21
  resources:
11
22
  limits:
data/docs/deny.rb ADDED
@@ -0,0 +1,59 @@
1
+ require_relative '../lib/decouplio'
2
+
3
+ class SemanticDeny
4
+ def self.call(ctx:, error_store:, semantic:, error_message:)
5
+ ctx[:semantic] = semantic
6
+ error_store.add_error(semantic, error_message)
7
+ end
8
+ end
9
+
10
+ class SomeAction < Decouplio::Action
11
+ logic do
12
+ step :step_one
13
+ deny SemanticDeny, semantic: :bad_request, error_message: 'Bad request'
14
+ step :step_two
15
+ end
16
+
17
+ def step_one(step_one_param:, **)
18
+ ctx[:step_one] = step_one_param
19
+ end
20
+
21
+ def step_two(**)
22
+ ctx[:step_two] = 'Success'
23
+ end
24
+
25
+ def fail_one(**)
26
+ ctx[:fail_one] = 'Failure'
27
+ end
28
+ end
29
+
30
+ success_action = SomeAction.call(step_one_param: true)
31
+ failure_action = SomeAction.call(step_one_param: false)
32
+
33
+ success_action # =>
34
+ # Result: success
35
+
36
+ # Railway Flow:
37
+ # step_one -> step_two
38
+
39
+ # Context:
40
+ # :step_one_param => true
41
+ # :step_one => true
42
+ # :step_two => "Success"
43
+
44
+ # Errors:
45
+ # None
46
+
47
+ failure_action # =>
48
+ # Result: failure
49
+
50
+ # Railway Flow:
51
+ # step_one -> SemanticDeny
52
+
53
+ # Context:
54
+ # :step_one_param => false
55
+ # :step_one => false
56
+ # :semantic => :bad_request
57
+
58
+ # Errors:
59
+ # :bad_request => ["Bad request"]
data/docs/doby.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require_relative '../lib/decouplio'
2
2
 
3
3
  class AssignDoby
4
- def self.call(ctx:, to:, from: nil, value: nil)
4
+ def self.call(ctx:, to:, from: nil, value: nil, **)
5
5
  raise 'from/value is empty' unless from || value
6
6
 
7
7
  ctx[to] = value || ctx[from]