decouplio 1.0.0alpha2 → 1.0.0alpha5

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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +11 -1
  3. data/.rubocop.yml +6 -0
  4. data/.ruby-version +1 -1
  5. data/README.md +2 -17
  6. data/benchmarks/multi_step_benchmark.rb +11 -10
  7. data/benchmarks/single_step_benchmark.rb +1 -1
  8. data/decouplio.gemspec +4 -4
  9. data/lib/decouplio/action.rb +12 -0
  10. data/lib/decouplio/composer.rb +47 -24
  11. data/lib/decouplio/const/doby_aide_options.rb +16 -0
  12. data/lib/decouplio/const/error_messages.rb +9 -0
  13. data/lib/decouplio/const/types.rb +14 -6
  14. data/lib/decouplio/const/validations/aide.rb +38 -0
  15. data/lib/decouplio/const/validations/doby.rb +36 -0
  16. data/lib/decouplio/const/validations/fail.rb +4 -0
  17. data/lib/decouplio/const/validations/octo.rb +2 -1
  18. data/lib/decouplio/errors/{deny_can_not_be_first_step_error.rb → aide_can_not_be_first_step_error.rb} +3 -3
  19. data/lib/decouplio/errors/aide_controversial_keys_error.rb +26 -0
  20. data/lib/decouplio/errors/aide_finish_him_error.rb +26 -0
  21. data/lib/decouplio/errors/doby_controversial_keys_error.rb +26 -0
  22. data/lib/decouplio/errors/doby_finish_him_error.rb +26 -0
  23. data/lib/decouplio/errors/execution_error.rb +20 -0
  24. data/lib/decouplio/errors/step_is_not_defined_for_aide_error.rb +26 -0
  25. data/lib/decouplio/errors/step_is_not_defined_for_doby_error.rb +27 -0
  26. data/lib/decouplio/errors/step_is_not_defined_for_pass_error.rb +27 -0
  27. data/lib/decouplio/logic_dsl.rb +23 -8
  28. data/lib/decouplio/options_validator.rb +157 -13
  29. data/lib/decouplio/steps/aide.rb +37 -0
  30. data/lib/decouplio/steps/base_resq.rb +13 -3
  31. data/lib/decouplio/steps/doby.rb +9 -8
  32. data/lib/decouplio/steps/octo.rb +7 -2
  33. data/lib/decouplio/validators/condition.rb +10 -0
  34. data/lib/decouplio/version.rb +1 -1
  35. metadata +24 -42
  36. data/docs/_config.yml +0 -1
  37. data/docs/benchmarks.md +0 -1
  38. data/docs/context.md +0 -74
  39. data/docs/context.rb +0 -62
  40. data/docs/deny.rb +0 -59
  41. data/docs/doby.rb +0 -38
  42. data/docs/doby_deny.md +0 -171
  43. data/docs/error_store.md +0 -347
  44. data/docs/error_store.rb +0 -202
  45. data/docs/fail.md +0 -1159
  46. data/docs/fail.rb +0 -859
  47. data/docs/index.md +0 -25
  48. data/docs/inner_action.md +0 -63
  49. data/docs/inner_action.rb +0 -43
  50. data/docs/logic_block.md +0 -25
  51. data/docs/octo.md +0 -269
  52. data/docs/octo.rb +0 -164
  53. data/docs/pass.md +0 -309
  54. data/docs/pass.rb +0 -213
  55. data/docs/quick_start.md +0 -71
  56. data/docs/quick_start.rb +0 -38
  57. data/docs/resq.md +0 -263
  58. data/docs/resq.rb +0 -176
  59. data/docs/step.md +0 -885
  60. data/docs/step.rb +0 -627
  61. data/docs/step_as_a_service.md +0 -123
  62. data/docs/step_as_a_service.rb +0 -77
  63. data/docs/wrap.md +0 -240
  64. data/docs/wrap.rb +0 -137
  65. data/lib/decouplio/const/validations/deny.rb +0 -11
  66. data/lib/decouplio/steps/deny.rb +0 -31
@@ -1,123 +0,0 @@
1
- # Step as a service
2
-
3
- It's similar to [Inner action](https://github.com/differencialx/decouplio/blob/master/docs/inner_action.md), but instead of using `Decouplio::Action`, you can use PORO class.
4
-
5
- ## Signature
6
-
7
- ```ruby
8
- (step|fail|pass)(service_class, **options)
9
- ```
10
-
11
- ## Behavior
12
-
13
- - service class should implement `.call` class method
14
- - service class can be used as `step` or `fail` or `pass`
15
- - all options of `step|fail|pass` can be used as for [Inner action](https://github.com/differencialx/decouplio/blob/master/docs/inner_action.md)
16
- - depending on returning value of `.call` method(truthy ot falsy) the execution will be moved to `success or failure` track accordingly.
17
-
18
- ## How to use?
19
-
20
- Create a PORO class with `.call` class method.
21
-
22
- ```ruby
23
- # :ctx - it's a ctx from Decouplio::Action
24
- # :error_store - it's an error_store from Decouplio::Action,
25
- # you can call #add_error on it
26
- class Concat
27
- def self.call(ctx:, **)
28
- new(ctx: ctx).call
29
- end
30
-
31
- def initialize(ctx:)
32
- @ctx = ctx
33
- end
34
-
35
- def call
36
- @ctx[:result] = @ctx[:one] + @ctx[:two]
37
- end
38
- end
39
-
40
- # OR
41
-
42
- # :ctx - it's a ctx from Decouplio::Action
43
- # :error_store - it's an error_store from Decouplio::Action,
44
- # you can call #add_error on it
45
- class Subtract
46
- def self.call(ctx:, **)
47
- ctx[:result] = ctx[:one] - ctx[:two]
48
- end
49
- end
50
-
51
- # OR
52
-
53
- class MakeRequest
54
- def self.call(ctx:, error_store:)
55
- ctx[:client].get(ctx[:url])
56
- rescue Net::OpenTimeout => error
57
- error_store.add_error(:connection_error, error.message)
58
- end
59
- end
60
- ```
61
-
62
- Now you can use these classes as a `step|fail|pass` step
63
-
64
- ```ruby
65
- class SomeActionConcat < Decouplio::Action
66
- logic do
67
- step Concat
68
- end
69
- end
70
-
71
- action = SomeActionConcat.call(one: 1, two: 2)
72
-
73
- puts action[:result] # => 3
74
-
75
- puts action # =>
76
- # Result: success
77
-
78
- # Railway Flow:
79
- # Concat
80
-
81
- # Context:
82
- # {:one=>1, :two=>2, :result=>3}
83
-
84
- # Errors:
85
- # {}
86
- ```
87
-
88
- OR
89
-
90
- ```ruby
91
- class SomeActionSubtract < Decouplio::Action
92
- logic do
93
- step :init_one
94
- step :init_two
95
- step Subtract
96
- end
97
-
98
- def init_one(param_one:, **)
99
- ctx[:one] = param_one
100
- end
101
-
102
- def init_two(param_two:, **)
103
- ctx[:two] = param_two
104
- end
105
- end
106
-
107
- action = SomeActionSubtract.call(param_one: 5, param_two: 2)
108
-
109
- puts action[:result] # => 3
110
-
111
- puts action # =>
112
- # Result: success
113
-
114
- # Railway Flow:
115
- # init_one -> init_two -> Subtract
116
-
117
- # Context:
118
- # {:param_one=>5, :param_two=>2, :one=>5, :two=>2, :result=>3}
119
-
120
- # Errors:
121
- # {}
122
-
123
- ```
@@ -1,77 +0,0 @@
1
- require_relative '../lib/decouplio'
2
-
3
- class Concat
4
- def self.call(ctx:, **)
5
- new(ctx: ctx).call
6
- end
7
-
8
- def initialize(ctx:)
9
- @ctx = ctx
10
- end
11
-
12
- def call
13
- @ctx[:result] = @ctx[:one] + @ctx[:two]
14
- end
15
- end
16
-
17
- class Subtract
18
- def self.call(ctx:, **)
19
- ctx[:result] = ctx[:one] - ctx[:two]
20
- end
21
- end
22
-
23
- class SomeActionConcat < Decouplio::Action
24
- logic do
25
- step Concat
26
- end
27
- end
28
-
29
- action = SomeActionConcat.call(one: 1, two: 2)
30
-
31
- puts action[:result] # => 3
32
-
33
- puts action # =>
34
- # Result: success
35
-
36
- # Railway Flow:
37
- # Concat
38
-
39
- # Context:
40
- # {:one=>1, :two=>2, :result=>3}
41
-
42
- # Errors:
43
- # {}
44
-
45
-
46
-
47
- class SomeActionSubtract < Decouplio::Action
48
- logic do
49
- step :init_one
50
- step :init_two
51
- step Subtract
52
- end
53
-
54
- def init_one(param_one:, **)
55
- ctx[:one] = param_one
56
- end
57
-
58
- def init_two(param_two:, **)
59
- ctx[:two] = param_two
60
- end
61
- end
62
-
63
- action = SomeActionSubtract.call(param_one: 5, param_two: 2)
64
-
65
- puts action[:result] # => 3
66
-
67
- puts action # =>
68
- # Result: success
69
-
70
- # Railway Flow:
71
- # init_one -> init_two -> Subtract
72
-
73
- # Context:
74
- # {:param_one=>5, :param_two=>2, :one=>5, :two=>2, :result=>3}
75
-
76
- # Errors:
77
- # {}
data/docs/wrap.md DELETED
@@ -1,240 +0,0 @@
1
- # Wrap
2
-
3
- `wrap` is the type of step, that behaves like `step`, but can wrap several steps with block to make some pre/post actions or to [rescue an error](https://github.com/differencialx/decouplio/blob/master/docs/resq.md).
4
-
5
- ## Signature
6
-
7
- ```ruby
8
- wrap(wrap_name, **options) do
9
- # steps to wrap
10
- end
11
- ```
12
-
13
- ## Behavior
14
-
15
- - all steps inside `wrap` step will be perceived as [inner action](https://github.com/differencialx/decouplio/blob/master/docs/inner_action.md). So depending on inner action result the `wrap` step will be move to success or failure track
16
-
17
- <details><summary><b>EXAMPLE (CLICK ME)</b></summary>
18
- <p>
19
-
20
- ```ruby
21
- require 'decouplio'
22
-
23
- class SomeAction < Decouplio::Action
24
- logic do
25
- step :step_one
26
-
27
- wrap :wrap_one do
28
- step :step_two
29
- fail :fail_one
30
- end
31
-
32
- step :step_three
33
- fail :fail_two
34
- end
35
-
36
- def step_one(param_for_step_one:, **)
37
- ctx[:step_one] = param_for_step_one
38
- end
39
-
40
- def step_two(param_for_step_two:, **)
41
- ctx[:step_two]= param_for_step_two
42
- end
43
-
44
- def fail_one(**)
45
- ctx[:fail_one] = 'Fail one failure'
46
- end
47
-
48
- def step_three(**)
49
- ctx[:step_three] = 'Success'
50
- end
51
-
52
- def fail_two(**)
53
- ctx[:fail_two] = 'Fail two failure'
54
- end
55
- end
56
-
57
- success_wrap_success = SomeAction.call(
58
- param_for_step_one: true,
59
- param_for_step_two: true
60
- )
61
- success_wrap_failure = SomeAction.call(
62
- param_for_step_one: true,
63
- param_for_step_two: false
64
- )
65
- failure = SomeAction.call(
66
- param_for_step_one: false
67
- )
68
-
69
- success_wrap_success # =>
70
- # Result: success
71
-
72
- # Railway Flow:
73
- # step_one -> wrap_one -> step_two -> step_three
74
-
75
- # Context:
76
- # {:param_for_step_one=>true, :param_for_step_two=>true, :step_one=>true, :step_two=>true, :step_three=>"Success"}
77
-
78
- # Errors:
79
- # {}
80
-
81
-
82
- success_wrap_failure # =>
83
- # Result: failure
84
-
85
- # Railway Flow:
86
- # step_one -> wrap_one -> step_two -> fail_one -> fail_two
87
-
88
- # Context:
89
- # {:param_for_step_one=>true, :param_for_step_two=>false, :step_one=>true, :step_two=>false, :fail_one=>"Fail one failure", :fail_two=>"Fail two failure"}
90
-
91
- # Errors:
92
- # {}
93
-
94
- failure # =>
95
- # Result: failure
96
-
97
- # Railway Flow:
98
- # step_one -> fail_two
99
-
100
- # Context:
101
- # {:param_for_step_one=>false, :step_one=>false, :fail_two=>"Fail two failure"}
102
-
103
- # Errors:
104
- # {}
105
- ```
106
-
107
- ```mermaid
108
- flowchart LR
109
- 1(start)-->2(step_one);
110
- 2(step_one)-->|success track|3(wrap_one);
111
- subgraph wrap action;
112
- 3(wrap_one)-->|success track|4(start);
113
- 4(start)-->5(step_two);
114
- 5(step_two)-->|success track|6(finish success);
115
- 5(step_two)-->|failure track|9(fail_one);
116
- 9(fail_one)-->|failure track|10(finish failure);
117
- end;
118
- 6(finish success)-->|success track|7(step_three);
119
- 7(step_three)-->|success track|8(finish success);
120
- 10(finish failure)-->|failure track|11(fail_two);
121
- 11(fail_two)-->|failure track|12(finish failure);
122
- 2(step_one)-->|failure track|11(fail_two)
123
- ```
124
-
125
- </p>
126
- </details>
127
-
128
- ***
129
-
130
- ## Options
131
-
132
- ### klass: some class, method: method to call on class
133
-
134
- |Option|Requirements|Description|
135
- |-|-|-|
136
- |:klass|:method option|The class which implements `method` for wrap|
137
- |:method|:klass option|The method which receives block as an argument|
138
-
139
- <details><summary><b>EXAMPLE (CLICK ME)</b></summary>
140
- <p>
141
-
142
- ```ruby
143
- require 'decouplio'
144
-
145
- class WrapperClass
146
- def self.some_wrapper_method(&block)
147
- if block_given?
148
- puts 'Before wrapper action execution'
149
- block.call
150
- puts 'After wrapper action execution'
151
- end
152
- end
153
- end
154
-
155
- class SomeActionWrapKlassMethod < Decouplio::Action
156
- logic do
157
- wrap :wrap_one, klass: WrapperClass, method: :some_wrapper_method do
158
- step :step_one
159
- step :step_two
160
- end
161
- end
162
-
163
- def step_one(**)
164
- puts 'Step one'
165
- ctx[:step_one] = 'Success'
166
- end
167
-
168
- def step_two(**)
169
- puts 'Step two'
170
- ctx[:step_two] = 'Success'
171
- end
172
- end
173
-
174
- action = SomeActionWrapKlassMethod.call # =>
175
- # Before wrapper action execution
176
- # Step one
177
- # Step two
178
- # After wrapper action execution
179
-
180
- action # =>
181
- # Result: success
182
-
183
- # Railway Flow:
184
- # wrap_one -> step_one -> step_two
185
-
186
- # Context:
187
- # {:step_one=>"Success", :step_two=>"Success"}
188
-
189
- # Errors:
190
- # {}
191
- ```
192
-
193
- ```mermaid
194
- flowchart LR
195
- 1(start)-->2(wrap_one);
196
- subgraph wrap action;
197
- 2(wrap_one)-->|success track|3(step_one);
198
- 3(step_one)-->|success track|4(step_two);
199
- 4(step_two)-->|success track|5(finish success);
200
- end;
201
- 5(finish success)-->|success track|6(finish success)
202
- ```
203
-
204
- </p>
205
- </details>
206
-
207
- ***
208
-
209
- ### on_success:
210
- The same as for [step](https://github.com/differencialx/decouplio/blob/master/docs/step.md)
211
- ### on_success: :finish_him
212
- The same as for [step](https://github.com/differencialx/decouplio/blob/master/docs/step.md)
213
- ### on_success: next success track step
214
- The same as for [step](https://github.com/differencialx/decouplio/blob/master/docs/step.md)
215
- ### on_success: next failure track step
216
- The same as for [step](https://github.com/differencialx/decouplio/blob/master/docs/step.md)
217
- ### on_success: :PASS
218
- The same as for [step](https://github.com/differencialx/decouplio/blob/master/docs/step.md)
219
- ### on_success: :FAIL
220
- The same as for [step](https://github.com/differencialx/decouplio/blob/master/docs/step.md)
221
- ### on_failure:
222
- The same as for [step](https://github.com/differencialx/decouplio/blob/master/docs/step.md)
223
- ### on_failure: :finish_him
224
- The same as for [step](https://github.com/differencialx/decouplio/blob/master/docs/step.md)
225
- ### on_failure: next success track step
226
- The same as for [step](https://github.com/differencialx/decouplio/blob/master/docs/step.md)
227
- ### on_failure: next failure track step
228
- The same as for [step](https://github.com/differencialx/decouplio/blob/master/docs/step.md)
229
- ### on_failure: :PASS
230
- The same as for [step](https://github.com/differencialx/decouplio/blob/master/docs/step.md)
231
- ### on_failure: :FAIL
232
- The same as for [step](https://github.com/differencialx/decouplio/blob/master/docs/step.md)
233
- ### if: condition method name
234
- The same as for [step](https://github.com/differencialx/decouplio/blob/master/docs/step.md)
235
- ### unless: condition method name
236
- The same as for [step](https://github.com/differencialx/decouplio/blob/master/docs/step.md)
237
- ### finish_him: :on_success
238
- The same as for [step](https://github.com/differencialx/decouplio/blob/master/docs/step.md)
239
- ### finish_him: :on_failure
240
- The same as for [step](https://github.com/differencialx/decouplio/blob/master/docs/step.md)
data/docs/wrap.rb DELETED
@@ -1,137 +0,0 @@
1
- # Behavior
2
-
3
- require_relative '../lib/decouplio'
4
-
5
- class SomeAction < Decouplio::Action
6
- logic do
7
- step :step_one
8
-
9
- wrap :wrap_one do
10
- step :step_two
11
- fail :fail_one
12
- end
13
-
14
- step :step_three
15
- fail :fail_two
16
- end
17
-
18
- def step_one(param_for_step_one:, **)
19
- ctx[:step_one] = param_for_step_one
20
- end
21
-
22
- def step_two(param_for_step_two:, **)
23
- ctx[:step_two]= param_for_step_two
24
- end
25
-
26
- def fail_one(**)
27
- ctx[:fail_one] = 'Fail one failure'
28
- end
29
-
30
- def step_three(**)
31
- ctx[:step_three] = 'Success'
32
- end
33
-
34
- def fail_two(**)
35
- ctx[:fail_two] = 'Fail two failure'
36
- end
37
- end
38
-
39
- success_wrap_success = SomeAction.call(
40
- param_for_step_one: true,
41
- param_for_step_two: true
42
- )
43
- success_wrap_failure = SomeAction.call(
44
- param_for_step_one: true,
45
- param_for_step_two: false
46
- )
47
- failure = SomeAction.call(
48
- param_for_step_one: false
49
- )
50
-
51
- puts success_wrap_success # =>
52
- # Result: success
53
-
54
- # Railway Flow:
55
- # step_one -> wrap_one -> step_two -> step_three
56
-
57
- # Context:
58
- # {:param_for_step_one=>true, :param_for_step_two=>true, :step_one=>true, :step_two=>true, :step_three=>"Success"}
59
-
60
- # Errors:
61
- # {}
62
-
63
-
64
- puts success_wrap_failure # =>
65
- # Result: failure
66
-
67
- # Railway Flow:
68
- # step_one -> wrap_one -> step_two -> fail_one -> fail_two
69
-
70
- # Context:
71
- # {:param_for_step_one=>true, :param_for_step_two=>false, :step_one=>true, :step_two=>false, :fail_one=>"Fail one failure", :fail_two=>"Fail two failure"}
72
-
73
- # Errors:
74
- # {}
75
-
76
- puts failure # =>
77
- # Result: failure
78
-
79
- # Railway Flow:
80
- # step_one -> fail_two
81
-
82
- # Context:
83
- # {:param_for_step_one=>false, :step_one=>false, :fail_two=>"Fail two failure"}
84
-
85
- # Errors:
86
- # {}
87
-
88
-
89
-
90
-
91
- # klass: some class, method: method to call on class
92
- class WrapperClass
93
- def self.some_wrapper_method(&block)
94
- if block_given?
95
- puts 'Before wrapper action execution'
96
- block.call
97
- puts 'After wrapper action execution'
98
- end
99
- end
100
- end
101
-
102
- class SomeActionWrapKlassMethod < Decouplio::Action
103
- logic do
104
- wrap :wrap_one, klass: WrapperClass, method: :some_wrapper_method do
105
- step :step_one
106
- step :step_two
107
- end
108
- end
109
-
110
- def step_one(**)
111
- puts 'Step one'
112
- ctx[:step_one] = 'Success'
113
- end
114
-
115
- def step_two(**)
116
- puts 'Step two'
117
- ctx[:step_two] = 'Success'
118
- end
119
- end
120
-
121
- action = SomeActionWrapKlassMethod.call # =>
122
- # Before wrapper action execution
123
- # Step one
124
- # Step two
125
- # After wrapper action execution
126
-
127
- puts action # =>
128
- # Result: success
129
-
130
- # Railway Flow:
131
- # wrap_one -> step_one -> step_two
132
-
133
- # Context:
134
- # {:step_one=>"Success", :step_two=>"Success"}
135
-
136
- # Errors:
137
- # {}
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Decouplio
4
- module Const
5
- module Validations
6
- module Deny
7
- FIRST_STEP = '"deny" can not be the first step'
8
- end
9
- end
10
- end
11
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base_step'
4
-
5
- module Decouplio
6
- module Steps
7
- class Deny < Decouplio::Steps::BaseStep
8
- def initialize(name:, deny_class:, deny_options:)
9
- super()
10
- @name = name
11
- @deny_class = deny_class
12
- @deny_options = deny_options
13
- end
14
-
15
- def process(instance:)
16
- instance.append_railway_flow(@name)
17
- @deny_class.call(
18
- ctx: instance.ctx,
19
- error_store: instance.error_store,
20
- **@deny_options
21
- )
22
- resolve(instance: instance)
23
- end
24
-
25
- def resolve(instance:)
26
- instance.fail_action
27
- Decouplio::Const::Results::FAIL
28
- end
29
- end
30
- end
31
- end