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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +11 -1
- data/.rubocop.yml +6 -0
- data/.ruby-version +1 -1
- data/README.md +2 -17
- data/benchmarks/multi_step_benchmark.rb +11 -10
- data/benchmarks/single_step_benchmark.rb +1 -1
- data/decouplio.gemspec +4 -4
- data/lib/decouplio/action.rb +12 -0
- data/lib/decouplio/composer.rb +47 -24
- data/lib/decouplio/const/doby_aide_options.rb +16 -0
- data/lib/decouplio/const/error_messages.rb +9 -0
- data/lib/decouplio/const/types.rb +14 -6
- data/lib/decouplio/const/validations/aide.rb +38 -0
- data/lib/decouplio/const/validations/doby.rb +36 -0
- data/lib/decouplio/const/validations/fail.rb +4 -0
- data/lib/decouplio/const/validations/octo.rb +2 -1
- data/lib/decouplio/errors/{deny_can_not_be_first_step_error.rb → aide_can_not_be_first_step_error.rb} +3 -3
- data/lib/decouplio/errors/aide_controversial_keys_error.rb +26 -0
- data/lib/decouplio/errors/aide_finish_him_error.rb +26 -0
- data/lib/decouplio/errors/doby_controversial_keys_error.rb +26 -0
- data/lib/decouplio/errors/doby_finish_him_error.rb +26 -0
- data/lib/decouplio/errors/execution_error.rb +20 -0
- data/lib/decouplio/errors/step_is_not_defined_for_aide_error.rb +26 -0
- data/lib/decouplio/errors/step_is_not_defined_for_doby_error.rb +27 -0
- data/lib/decouplio/errors/step_is_not_defined_for_pass_error.rb +27 -0
- data/lib/decouplio/logic_dsl.rb +23 -8
- data/lib/decouplio/options_validator.rb +157 -13
- data/lib/decouplio/steps/aide.rb +37 -0
- data/lib/decouplio/steps/base_resq.rb +13 -3
- data/lib/decouplio/steps/doby.rb +9 -8
- data/lib/decouplio/steps/octo.rb +7 -2
- data/lib/decouplio/validators/condition.rb +10 -0
- data/lib/decouplio/version.rb +1 -1
- metadata +24 -42
- data/docs/_config.yml +0 -1
- data/docs/benchmarks.md +0 -1
- data/docs/context.md +0 -74
- data/docs/context.rb +0 -62
- data/docs/deny.rb +0 -59
- data/docs/doby.rb +0 -38
- data/docs/doby_deny.md +0 -171
- data/docs/error_store.md +0 -347
- data/docs/error_store.rb +0 -202
- data/docs/fail.md +0 -1159
- data/docs/fail.rb +0 -859
- data/docs/index.md +0 -25
- data/docs/inner_action.md +0 -63
- data/docs/inner_action.rb +0 -43
- data/docs/logic_block.md +0 -25
- data/docs/octo.md +0 -269
- data/docs/octo.rb +0 -164
- data/docs/pass.md +0 -309
- data/docs/pass.rb +0 -213
- data/docs/quick_start.md +0 -71
- data/docs/quick_start.rb +0 -38
- data/docs/resq.md +0 -263
- data/docs/resq.rb +0 -176
- data/docs/step.md +0 -885
- data/docs/step.rb +0 -627
- data/docs/step_as_a_service.md +0 -123
- data/docs/step_as_a_service.rb +0 -77
- data/docs/wrap.md +0 -240
- data/docs/wrap.rb +0 -137
- data/lib/decouplio/const/validations/deny.rb +0 -11
- data/lib/decouplio/steps/deny.rb +0 -31
data/docs/error_store.md
DELETED
@@ -1,347 +0,0 @@
|
|
1
|
-
# Error store
|
2
|
-
|
3
|
-
It's an object to store errors. By default `Decouplio::DefaultErrorHandler` is used for `Decouplio::Action`
|
4
|
-
|
5
|
-
```ruby
|
6
|
-
module Decouplio
|
7
|
-
class DefaultErrorHandler
|
8
|
-
attr_reader :errors
|
9
|
-
|
10
|
-
def initialize
|
11
|
-
@errors = {}
|
12
|
-
end
|
13
|
-
|
14
|
-
def add_error(key, message)
|
15
|
-
@errors.store(
|
16
|
-
key,
|
17
|
-
(@errors[key] || []) + [message].flatten
|
18
|
-
)
|
19
|
-
end
|
20
|
-
|
21
|
-
def merge(error_store)
|
22
|
-
@errors = @errors.merge(error_store.errors) do |_key, this_val, other_val|
|
23
|
-
this_val + other_val
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
```
|
29
|
-
|
30
|
-
## How to use
|
31
|
-
Inside step method you can call `#add_error` method
|
32
|
-
|
33
|
-
```ruby
|
34
|
-
add_error(key, message)
|
35
|
-
```
|
36
|
-
|
37
|
-
```ruby
|
38
|
-
require 'decouplio'
|
39
|
-
|
40
|
-
class SomeAction < Decouplio::Action
|
41
|
-
logic do
|
42
|
-
step :step_one
|
43
|
-
fail :fail_one
|
44
|
-
end
|
45
|
-
|
46
|
-
def step_one(**)
|
47
|
-
false
|
48
|
-
end
|
49
|
-
|
50
|
-
def fail_one(**)
|
51
|
-
add_error(:something_went_wrong, 'Something went wrong')
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
action = SomeAction.call
|
56
|
-
|
57
|
-
action # =>
|
58
|
-
# Result: failure
|
59
|
-
|
60
|
-
# Railway Flow:
|
61
|
-
# step_one -> fail_one
|
62
|
-
|
63
|
-
# Context:
|
64
|
-
# {}
|
65
|
-
|
66
|
-
# Errors:
|
67
|
-
# {:something_went_wrong=>["Something went wrong"]}
|
68
|
-
|
69
|
-
action.errors # =>
|
70
|
-
# {:something_went_wrong=>["Something went wrong"]}
|
71
|
-
```
|
72
|
-
|
73
|
-
## Behavior
|
74
|
-
|
75
|
-
- If error was added, it doesn't mean that action result is `failure`, action can be `success` and have errors, so basically `error store` is just a container for errors. Such behavior was implemented to provide more freedom.
|
76
|
-
- Error store for parent an inner action should be the same. It's because different error stores may have different `add_error` method signature and error hash structure.
|
77
|
-
|
78
|
-
## Custom error store
|
79
|
-
|
80
|
-
If you want to use your own custom error store then you can do it in this way:
|
81
|
-
|
82
|
-
- Define our own class with two public methods
|
83
|
-
- `#add_error(<signature you want>)` - method which adds error to `error_store`
|
84
|
-
- `#merge(error_store_to_merge)` - will be used by `Decouplio` to merge errors from inner actions to parent action.
|
85
|
-
- should have `attr_reader :errors`
|
86
|
-
|
87
|
-
<details><summary><b>EXAMPLE (CLICK ME)</b></summary>
|
88
|
-
<p>
|
89
|
-
|
90
|
-
```ruby
|
91
|
-
require 'decouplio'
|
92
|
-
|
93
|
-
class CustomErrorStore
|
94
|
-
attr_reader :errors
|
95
|
-
|
96
|
-
def initialize
|
97
|
-
@errors = {}
|
98
|
-
end
|
99
|
-
|
100
|
-
def add_error(key:, message:, namespace: :root)
|
101
|
-
@errors[namespace] ||= {}
|
102
|
-
@errors[namespace].store(
|
103
|
-
key,
|
104
|
-
(@errors[namespace][key] || []) + [message].flatten
|
105
|
-
)
|
106
|
-
end
|
107
|
-
|
108
|
-
def merge(error_store)
|
109
|
-
@errors = deep_merge(@errors, error_store.errors)
|
110
|
-
end
|
111
|
-
|
112
|
-
private
|
113
|
-
|
114
|
-
def deep_merge(this_hash, other_hash)
|
115
|
-
this_hash.merge(other_hash) do |_key, this_val, other_val|
|
116
|
-
if this_val.is_a?(Hash) && other_val.is_a?(Hash)
|
117
|
-
deep_merge(this_val, other_val)
|
118
|
-
else
|
119
|
-
this_val + other_val
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
class SomeActionWithCustomErrorStore < Decouplio::Action
|
126
|
-
error_store_class CustomErrorStore
|
127
|
-
|
128
|
-
logic do
|
129
|
-
step :step_one
|
130
|
-
step :step_two
|
131
|
-
end
|
132
|
-
|
133
|
-
def step_one(**)
|
134
|
-
add_error(
|
135
|
-
key: :under_root,
|
136
|
-
message: 'Error Message One'
|
137
|
-
)
|
138
|
-
end
|
139
|
-
|
140
|
-
def step_two(**)
|
141
|
-
add_error(
|
142
|
-
namespace: :step_two,
|
143
|
-
key: :error_happened,
|
144
|
-
message: 'Error Message Two'
|
145
|
-
)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
action = SomeActionWithCustomErrorStore.call
|
150
|
-
|
151
|
-
action # =>
|
152
|
-
# Result: success
|
153
|
-
|
154
|
-
# Railway Flow:
|
155
|
-
# step_one -> step_two
|
156
|
-
|
157
|
-
# Context:
|
158
|
-
# {}
|
159
|
-
|
160
|
-
# Errors:
|
161
|
-
# {:root=>{:under_root=>["Error Message One"]}, :step_two=>{:error_happened=>["Error Message Two"]}}
|
162
|
-
|
163
|
-
action.errors # =>
|
164
|
-
# {:root=>{:under_root=>["Error Message One"]}, :step_two=>{:error_happened=>["Error Message Two"]}}
|
165
|
-
```
|
166
|
-
|
167
|
-
</p>
|
168
|
-
</details>
|
169
|
-
|
170
|
-
***
|
171
|
-
|
172
|
-
## Custom error store and inner action
|
173
|
-
|
174
|
-
### When error store is the same for parent and inner action
|
175
|
-
<details><summary><b>EXAMPLE (CLICK ME)</b></summary>
|
176
|
-
<p>
|
177
|
-
|
178
|
-
```ruby
|
179
|
-
require 'decouplio'
|
180
|
-
|
181
|
-
class CustomErrorStore
|
182
|
-
attr_reader :errors
|
183
|
-
|
184
|
-
def initialize
|
185
|
-
@errors = {}
|
186
|
-
end
|
187
|
-
|
188
|
-
def add_error(key:, message:, namespace: :root)
|
189
|
-
@errors[namespace] ||= {}
|
190
|
-
@errors[namespace].store(
|
191
|
-
key,
|
192
|
-
(@errors[namespace][key] || []) + [message].flatten
|
193
|
-
)
|
194
|
-
end
|
195
|
-
|
196
|
-
def merge(error_store)
|
197
|
-
@errors = deep_merge(@errors, error_store.errors)
|
198
|
-
end
|
199
|
-
|
200
|
-
private
|
201
|
-
|
202
|
-
def deep_merge(this_hash, other_hash)
|
203
|
-
this_hash.merge(other_hash) do |_key, this_val, other_val|
|
204
|
-
if this_val.is_a?(Hash) && other_val.is_a?(Hash)
|
205
|
-
deep_merge(this_val, other_val)
|
206
|
-
else
|
207
|
-
this_val + other_val
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
class InnerActionWithCustomErrorStore < Decouplio::Action
|
214
|
-
error_store_class CustomErrorStore
|
215
|
-
|
216
|
-
logic do
|
217
|
-
step :inner_step
|
218
|
-
end
|
219
|
-
|
220
|
-
def inner_step(**)
|
221
|
-
add_error(
|
222
|
-
namespace: :inner,
|
223
|
-
key: :inner_key,
|
224
|
-
message: 'Somebody was told me...'
|
225
|
-
)
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
class ParentActionWithCustomErrorStore < Decouplio::Action
|
230
|
-
error_store_class CustomErrorStore
|
231
|
-
|
232
|
-
logic do
|
233
|
-
step :step_one, action: InnerActionWithCustomErrorStore
|
234
|
-
step :step_two
|
235
|
-
end
|
236
|
-
|
237
|
-
def step_two(**)
|
238
|
-
add_error(
|
239
|
-
namespace: :parent,
|
240
|
-
key: :error_happened,
|
241
|
-
message: 'Message'
|
242
|
-
)
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
|
-
action = ParentActionWithCustomErrorStore.call
|
247
|
-
|
248
|
-
puts action # =>
|
249
|
-
# Result: success
|
250
|
-
|
251
|
-
# Railway Flow:
|
252
|
-
# step_one -> inner_step -> step_two
|
253
|
-
|
254
|
-
# Context:
|
255
|
-
# {}
|
256
|
-
|
257
|
-
# Errors:
|
258
|
-
# {:inner=>{:inner_key=>["Somebody was told me..."]}, :parent=>{:error_happened=>["Message"]}}
|
259
|
-
|
260
|
-
puts action.errors # =>
|
261
|
-
# {:inner=>{:inner_key=>["Somebody was told me..."]}, :parent=>{:error_happened=>["Message"]}}
|
262
|
-
|
263
|
-
```
|
264
|
-
|
265
|
-
</p>
|
266
|
-
</details>
|
267
|
-
|
268
|
-
***
|
269
|
-
|
270
|
-
### When error store is different for parent and inner action
|
271
|
-
If inner action error store is different from parent action error store then error will be raised.
|
272
|
-
|
273
|
-
<details><summary><b>EXAMPLE (CLICK ME)</b></summary>
|
274
|
-
<p>
|
275
|
-
|
276
|
-
```ruby
|
277
|
-
require 'decouplio'
|
278
|
-
|
279
|
-
class CustomErrorStore
|
280
|
-
attr_reader :errors
|
281
|
-
|
282
|
-
def initialize
|
283
|
-
@errors = {}
|
284
|
-
end
|
285
|
-
|
286
|
-
def add_error(key:, message:, namespace: :root)
|
287
|
-
@errors[namespace] ||= {}
|
288
|
-
@errors[namespace].store(
|
289
|
-
key,
|
290
|
-
(@errors[namespace][key] || []) + [message].flatten
|
291
|
-
)
|
292
|
-
end
|
293
|
-
|
294
|
-
def merge(error_store)
|
295
|
-
@errors = deep_merge(@errors, error_store.errors)
|
296
|
-
end
|
297
|
-
|
298
|
-
private
|
299
|
-
|
300
|
-
def deep_merge(this_hash, other_hash)
|
301
|
-
this_hash.merge(other_hash) do |_key, this_val, other_val|
|
302
|
-
if this_val.is_a?(Hash) && other_val.is_a?(Hash)
|
303
|
-
deep_merge(this_val, other_val)
|
304
|
-
else
|
305
|
-
this_val + other_val
|
306
|
-
end
|
307
|
-
end
|
308
|
-
end
|
309
|
-
end
|
310
|
-
|
311
|
-
class InnerActionWithDefaultErrorStore < Decouplio::Action
|
312
|
-
logic do
|
313
|
-
step :inner_step
|
314
|
-
end
|
315
|
-
|
316
|
-
def inner_step(**)
|
317
|
-
add_error(
|
318
|
-
key: :inner_key,
|
319
|
-
message: 'Somebody was told me...'
|
320
|
-
)
|
321
|
-
end
|
322
|
-
end
|
323
|
-
|
324
|
-
class ParentActionForInnerActionDefaultErrorStore < Decouplio::Action
|
325
|
-
error_store_class CustomErrorStore
|
326
|
-
|
327
|
-
logic do
|
328
|
-
step :step_one, action: InnerActionWithDefaultErrorStore
|
329
|
-
step :step_two
|
330
|
-
end
|
331
|
-
|
332
|
-
def step_two(**)
|
333
|
-
add_error(
|
334
|
-
namespace: :parent,
|
335
|
-
key: :error_happened,
|
336
|
-
message: 'Message'
|
337
|
-
)
|
338
|
-
end
|
339
|
-
end # =>
|
340
|
-
# Error store for action and inner action should be the same. (Decouplio::Errors::ErrorStoreError)
|
341
|
-
|
342
|
-
```
|
343
|
-
|
344
|
-
</p>
|
345
|
-
</details>
|
346
|
-
|
347
|
-
***
|
data/docs/error_store.rb
DELETED
@@ -1,202 +0,0 @@
|
|
1
|
-
require_relative '../lib/decouplio'
|
2
|
-
|
3
|
-
# How to use
|
4
|
-
class SomeAction < Decouplio::Action
|
5
|
-
logic do
|
6
|
-
step :step_one
|
7
|
-
fail :fail_one
|
8
|
-
end
|
9
|
-
|
10
|
-
def step_one(**)
|
11
|
-
false
|
12
|
-
end
|
13
|
-
|
14
|
-
def fail_one(**)
|
15
|
-
add_error(:something_went_wrong, 'Something went wrong')
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
action = SomeAction.call
|
20
|
-
|
21
|
-
puts action # =>
|
22
|
-
# Result: failure
|
23
|
-
|
24
|
-
# Railway Flow:
|
25
|
-
# step_one -> fail_one
|
26
|
-
|
27
|
-
# Context:
|
28
|
-
# {}
|
29
|
-
|
30
|
-
# Errors:
|
31
|
-
# {:something_went_wrong=>["Something went wrong"]}
|
32
|
-
|
33
|
-
puts action.errors # =>
|
34
|
-
# {:something_went_wrong=>["Something went wrong"]}
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
# Custom error store
|
40
|
-
class CustomErrorStore
|
41
|
-
attr_reader :errors
|
42
|
-
|
43
|
-
def initialize
|
44
|
-
@errors = {}
|
45
|
-
end
|
46
|
-
|
47
|
-
def add_error(key:, message:, namespace: :root)
|
48
|
-
@errors[namespace] ||= {}
|
49
|
-
@errors[namespace].store(
|
50
|
-
key,
|
51
|
-
(@errors[namespace][key] || []) + [message].flatten
|
52
|
-
)
|
53
|
-
end
|
54
|
-
|
55
|
-
def merge(error_store)
|
56
|
-
@errors = deep_merge(@errors, error_store.errors)
|
57
|
-
end
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
|
-
def deep_merge(this_hash, other_hash)
|
62
|
-
this_hash.merge(other_hash) do |_key, this_val, other_val|
|
63
|
-
if this_val.is_a?(Hash) && other_val.is_a?(Hash)
|
64
|
-
deep_merge(this_val, other_val)
|
65
|
-
else
|
66
|
-
this_val + other_val
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
class SomeActionWithCustomErrorStore < Decouplio::Action
|
73
|
-
error_store_class CustomErrorStore
|
74
|
-
|
75
|
-
logic do
|
76
|
-
step :step_one
|
77
|
-
step :step_two
|
78
|
-
end
|
79
|
-
|
80
|
-
def step_one(**)
|
81
|
-
add_error(
|
82
|
-
key: :under_root,
|
83
|
-
message: 'Error Message One'
|
84
|
-
)
|
85
|
-
end
|
86
|
-
|
87
|
-
def step_two(**)
|
88
|
-
add_error(
|
89
|
-
namespace: :step_two,
|
90
|
-
key: :error_happened,
|
91
|
-
message: 'Error Message Two'
|
92
|
-
)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
action = SomeActionWithCustomErrorStore.call
|
97
|
-
|
98
|
-
puts action # =>
|
99
|
-
# Result: success
|
100
|
-
|
101
|
-
# Railway Flow:
|
102
|
-
# step_one -> step_two
|
103
|
-
|
104
|
-
# Context:
|
105
|
-
# {}
|
106
|
-
|
107
|
-
# Errors:
|
108
|
-
# {:root=>{:under_root=>["Error Message One"]}, :step_two=>{:error_happened=>["Error Message Two"]}}
|
109
|
-
|
110
|
-
puts action.errors # =>
|
111
|
-
# {:root=>{:under_root=>["Error Message One"]}, :step_two=>{:error_happened=>["Error Message Two"]}}
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
# When error store is the same for parent and inner action
|
117
|
-
|
118
|
-
class InnerActionWithCustomErrorStore < Decouplio::Action
|
119
|
-
error_store_class CustomErrorStore
|
120
|
-
|
121
|
-
logic do
|
122
|
-
step :inner_step
|
123
|
-
end
|
124
|
-
|
125
|
-
def inner_step(**)
|
126
|
-
add_error(
|
127
|
-
namespace: :inner,
|
128
|
-
key: :inner_key,
|
129
|
-
message: 'Somebody was told me...'
|
130
|
-
)
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
class ParentActionWithCustomErrorStore < Decouplio::Action
|
135
|
-
error_store_class CustomErrorStore
|
136
|
-
|
137
|
-
logic do
|
138
|
-
step :step_one, action: InnerActionWithCustomErrorStore
|
139
|
-
step :step_two
|
140
|
-
end
|
141
|
-
|
142
|
-
def step_two(**)
|
143
|
-
add_error(
|
144
|
-
namespace: :parent,
|
145
|
-
key: :error_happened,
|
146
|
-
message: 'Message'
|
147
|
-
)
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
action = ParentActionWithCustomErrorStore.call
|
152
|
-
|
153
|
-
puts action # =>
|
154
|
-
# Result: success
|
155
|
-
|
156
|
-
# Railway Flow:
|
157
|
-
# step_one -> inner_step -> step_two
|
158
|
-
|
159
|
-
# Context:
|
160
|
-
# {}
|
161
|
-
|
162
|
-
# Errors:
|
163
|
-
# {:inner=>{:inner_key=>["Somebody was told me..."]}, :parent=>{:error_happened=>["Message"]}}
|
164
|
-
|
165
|
-
puts action.errors # =>
|
166
|
-
# {:inner=>{:inner_key=>["Somebody was told me..."]}, :parent=>{:error_happened=>["Message"]}}
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
# When error store is different for parent and inner action
|
172
|
-
|
173
|
-
class InnerActionWithDefaultErrorStore < Decouplio::Action
|
174
|
-
logic do
|
175
|
-
step :inner_step
|
176
|
-
end
|
177
|
-
|
178
|
-
def inner_step(**)
|
179
|
-
add_error(
|
180
|
-
key: :inner_key,
|
181
|
-
message: 'Somebody was told me...'
|
182
|
-
)
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
class ParentActionForInnerActionDefaultErrorStore < Decouplio::Action
|
187
|
-
error_store_class CustomErrorStore
|
188
|
-
|
189
|
-
logic do
|
190
|
-
step :step_one, action: InnerActionWithDefaultErrorStore
|
191
|
-
step :step_two
|
192
|
-
end
|
193
|
-
|
194
|
-
def step_two(**)
|
195
|
-
add_error(
|
196
|
-
namespace: :parent,
|
197
|
-
key: :error_happened,
|
198
|
-
message: 'Message'
|
199
|
-
)
|
200
|
-
end
|
201
|
-
end # =>
|
202
|
-
# Error store for action and inner action should be the same. (Decouplio::Errors::ErrorStoreError)
|