decouplio 1.0.0alpha8 → 1.0.0rc

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +313 -15
  3. data/decouplio.gemspec +8 -2
  4. data/lib/decouplio/action.rb +24 -40
  5. data/lib/decouplio/action_state_printer.rb +2 -5
  6. data/lib/decouplio/const/flows.rb +59 -0
  7. data/lib/decouplio/const/reserved_methods.rb +6 -13
  8. data/lib/decouplio/const/types.rb +0 -144
  9. data/lib/decouplio/const/validations/common.rb +10 -0
  10. data/lib/decouplio/const/validations/octo.rb +16 -0
  11. data/lib/decouplio/const/validations/resq.rb +12 -1
  12. data/lib/decouplio/ctx.rb +13 -0
  13. data/lib/decouplio/default_meta_store.rb +2 -4
  14. data/lib/decouplio/errors/action_class_error.rb +0 -3
  15. data/lib/decouplio/errors/base_error.rb +0 -3
  16. data/lib/decouplio/errors/execution_error.rb +0 -2
  17. data/lib/decouplio/errors/extra_key_for_pass_error.rb +0 -3
  18. data/lib/decouplio/errors/fail_can_not_be_first_step_error.rb +0 -3
  19. data/lib/decouplio/errors/fail_controversial_keys_error.rb +0 -3
  20. data/lib/decouplio/errors/fail_finish_him_error.rb +0 -3
  21. data/lib/decouplio/errors/invalid_error_class_error.rb +0 -3
  22. data/lib/decouplio/errors/invalid_options_for_resq_step.rb +18 -0
  23. data/lib/decouplio/errors/invalid_wrap_name_error.rb +0 -3
  24. data/lib/decouplio/errors/logic_is_not_defined_error.rb +0 -3
  25. data/lib/decouplio/errors/logic_redefinition_error.rb +0 -3
  26. data/lib/decouplio/errors/octo_block_is_not_defined_error.rb +0 -3
  27. data/lib/decouplio/errors/octo_case_is_not_defined_error.rb +19 -0
  28. data/lib/decouplio/errors/octo_controversial_keys_error.rb +0 -3
  29. data/lib/decouplio/errors/{error_store_error.rb → octo_finish_him_is_not_allowed_error.rb} +2 -4
  30. data/lib/decouplio/errors/options_validation_error.rb +13 -1
  31. data/lib/decouplio/errors/palp_block_is_not_defined_error.rb +0 -3
  32. data/lib/decouplio/errors/palp_validation_error.rb +0 -3
  33. data/lib/decouplio/errors/pass_controversial_keys_error.rb +0 -3
  34. data/lib/decouplio/errors/pass_finish_him_error.rb +0 -3
  35. data/lib/decouplio/errors/required_options_is_missing_for_octo_error.rb +0 -3
  36. data/lib/decouplio/errors/resq_definition_error.rb +0 -3
  37. data/lib/decouplio/errors/resq_error_class_error.rb +0 -3
  38. data/lib/decouplio/errors/resq_handler_method_error.rb +0 -3
  39. data/lib/decouplio/errors/step_controversial_keys_error.rb +0 -3
  40. data/lib/decouplio/errors/step_definition_error.rb +17 -0
  41. data/lib/decouplio/errors/step_finish_him_error.rb +0 -3
  42. data/lib/decouplio/errors/step_is_not_defined_for_fail_error.rb +0 -3
  43. data/lib/decouplio/errors/step_is_not_defined_for_pass_error.rb +0 -4
  44. data/lib/decouplio/errors/step_is_not_defined_for_step_error.rb +0 -4
  45. data/lib/decouplio/errors/step_is_not_defined_for_wrap_error.rb +0 -3
  46. data/lib/decouplio/errors/step_name_error.rb +0 -3
  47. data/lib/decouplio/errors/wrap_block_is_not_defined_error.rb +0 -3
  48. data/lib/decouplio/errors/wrap_controversial_keys_error.rb +0 -3
  49. data/lib/decouplio/errors/wrap_finish_him_error.rb +0 -3
  50. data/lib/decouplio/errors/wrap_klass_method_error.rb +0 -3
  51. data/lib/decouplio/graph.rb +9 -0
  52. data/lib/decouplio/logic_dsl.rb +340 -79
  53. data/lib/decouplio/new_flow.rb +283 -0
  54. data/lib/decouplio/octo_hash_case.rb +20 -5
  55. data/lib/decouplio/octo_options_validator.rb +10 -64
  56. data/lib/decouplio/step_validator.rb +200 -0
  57. data/lib/decouplio/steps/base_condition.rb +21 -0
  58. data/lib/decouplio/steps/base_if_condition.rb +11 -0
  59. data/lib/decouplio/steps/base_inner_action.rb +42 -0
  60. data/lib/decouplio/steps/base_octo.rb +26 -0
  61. data/lib/decouplio/steps/base_resq.rb +25 -28
  62. data/lib/decouplio/steps/base_resq_with_mapping.rb +34 -0
  63. data/lib/decouplio/steps/base_service_step.rb +39 -0
  64. data/lib/decouplio/steps/base_step.rb +33 -6
  65. data/lib/decouplio/steps/base_unless_condition.rb +11 -0
  66. data/lib/decouplio/steps/base_wrap.rb +27 -0
  67. data/lib/decouplio/steps/fail.rb +1 -28
  68. data/lib/decouplio/steps/if_condition_fail.rb +1 -21
  69. data/lib/decouplio/steps/if_condition_pass.rb +1 -19
  70. data/lib/decouplio/steps/inner_action_fail.rb +1 -35
  71. data/lib/decouplio/steps/inner_action_pass.rb +9 -29
  72. data/lib/decouplio/steps/inner_action_step.rb +1 -35
  73. data/lib/decouplio/steps/octo_by_key.rb +31 -0
  74. data/lib/decouplio/steps/octo_by_method.rb +31 -0
  75. data/lib/decouplio/steps/pass.rb +5 -26
  76. data/lib/decouplio/steps/resq_fail.rb +0 -2
  77. data/lib/decouplio/steps/resq_pass.rb +1 -3
  78. data/lib/decouplio/steps/resq_with_mapping_fail.rb +8 -0
  79. data/lib/decouplio/steps/resq_with_mapping_pass.rb +8 -0
  80. data/lib/decouplio/steps/service_as_fail.rb +8 -0
  81. data/lib/decouplio/steps/service_as_pass.rb +16 -0
  82. data/lib/decouplio/steps/service_as_step.rb +8 -0
  83. data/lib/decouplio/steps/step.rb +0 -24
  84. data/lib/decouplio/steps/unless_condition_fail.rb +1 -21
  85. data/lib/decouplio/steps/unless_condition_pass.rb +1 -19
  86. data/lib/decouplio/steps/wrap.rb +25 -37
  87. data/lib/decouplio/steps/wrap_with_class.rb +43 -0
  88. data/lib/decouplio/steps/wrap_with_class_method.rb +45 -0
  89. data/lib/decouplio/utils/prepare_resq_mappings.rb +17 -0
  90. data/lib/decouplio/version.rb +1 -1
  91. data/lib/decouplio.rb +93 -0
  92. metadata +30 -42
  93. data/.circleci/config.yml +0 -63
  94. data/.dockerignore +0 -12
  95. data/.gitignore +0 -13
  96. data/.rspec +0 -3
  97. data/.rubocop.yml +0 -108
  98. data/.rubocop_todo.yml +0 -147
  99. data/.ruby-version +0 -1
  100. data/.vscode/settings.json +0 -3
  101. data/Dockerfile +0 -12
  102. data/Gemfile +0 -8
  103. data/benchmarks/.ruby-version +0 -1
  104. data/benchmarks/Dockerfile +0 -12
  105. data/benchmarks/Gemfile +0 -12
  106. data/benchmarks/multi_step_benchmark.rb +0 -336
  107. data/benchmarks/single_step_benchmark.rb +0 -159
  108. data/bin/console +0 -15
  109. data/bin/setup +0 -8
  110. data/docker-compose.yml +0 -29
  111. data/lib/decouplio/composer.rb +0 -615
  112. data/lib/decouplio/const/colors.rb +0 -25
  113. data/lib/decouplio/const/results.rb +0 -15
  114. data/lib/decouplio/const/step_options.rb +0 -16
  115. data/lib/decouplio/errors/extra_key_for_fail_error.rb +0 -26
  116. data/lib/decouplio/errors/extra_key_for_octo_error.rb +0 -26
  117. data/lib/decouplio/errors/extra_key_for_resq_error.rb +0 -29
  118. data/lib/decouplio/errors/extra_key_for_step_error.rb +0 -23
  119. data/lib/decouplio/errors/extra_key_for_wrap_error.rb +0 -23
  120. data/lib/decouplio/errors/palp_is_not_defined_error.rb +0 -26
  121. data/lib/decouplio/flow.rb +0 -17
  122. data/lib/decouplio/options_validator.rb +0 -606
  123. data/lib/decouplio/processor.rb +0 -20
  124. data/lib/decouplio/steps/octo.rb +0 -27
  125. data/lib/decouplio/steps/service_fail.rb +0 -41
  126. data/lib/decouplio/steps/service_pass.rb +0 -41
  127. data/lib/decouplio/steps/service_step.rb +0 -41
  128. data/lib/decouplio/steps/shared/fail_resolver.rb +0 -40
  129. data/lib/decouplio/steps/shared/step_resolver.rb +0 -43
  130. data/lib/decouplio/validators/condition.rb +0 -49
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 13faf170a6cfce8a57a5263eb8ba404ee1ceadcda93990c9c780987bd6a79a8e
4
- data.tar.gz: 18e855d3cbf016a0e1976e72147309db0ec0e91d764b1c7988cdb7172868c804
3
+ metadata.gz: 3f372ffe111d0d286f3c1898645caeb50be16ef3131b6749a28d0d8b43629392
4
+ data.tar.gz: 717430fa9380f5f4fcd8eb399b1399b47355bdc05860d253fce1b9ea105c5764
5
5
  SHA512:
6
- metadata.gz: 53426aa0ac2fdd513d7fb80dea55e4e5e1425b3ef08912fe53f3fefbdfa25773d8fa3dce9dc8a84efec89c8078f42756af1b741a34f9d937050a823f577bdfad
7
- data.tar.gz: 5209925b7857efa198cae3f9e2ceb1341cd160944ab9855557fea6bacb1762c3239f0b08a33abf837d5d610de36d157a761c132b053eed25b07c676ceaaf191d
6
+ metadata.gz: 011e581a2643ebfd78a93de90dd5e425cf062fe555d8c0f115a12066cf2a612118ba41e9975f97c7decced6bf1d44f805062b1170b558c9e32fd16bdd818c47e
7
+ data.tar.gz: 072a87e219c5a90ab64c3aebcd5bb61459108f3cdc3c69e1f0d28a772860cba47a9cd0a36912b8e412bda6d45e9b264aac8bc6ef962fcdb2fd0856e4c4e3f649
data/README.md CHANGED
@@ -2,37 +2,335 @@
2
2
 
3
3
  Decouplio is a zero dependency, thread safe and framework agnostic gem designed to encapsulate application business logic. It's reverse engineered through TDD and inspired by such frameworks and gems like Trailblazer, Interactor.
4
4
 
5
- ## Installation
5
+ # How to install?
6
6
 
7
- Add this line to your application's Gemfile:
7
+ ```
8
+ gem install decouplio --pre
9
+ ```
10
+
11
+ ### Gemfile
12
+ ```
13
+ gem 'decouplio', '~> 1.0.0rc'
14
+ ```
15
+
16
+ # Compatibility
17
+ Ruby:
18
+ - 2.7
19
+ - 3.0
20
+
21
+ # Quick reference to docs
22
+
23
+ |Options/Step type|[**step**](https://differencialx.github.io/decouplio.github.io/step/)|[**fail**](https://differencialx.github.io/decouplio.github.io/fail/)|[**pass**](https://differencialx.github.io/decouplio.github.io/pass/)|[**wrap**](https://differencialx.github.io/decouplio.github.io/wrap/)|[**octo**](https://differencialx.github.io/decouplio.github.io/octo/)|[**resq**](https://differencialx.github.io/decouplio.github.io/resq/)|
24
+ |:-|:-:|:-:|:-:|:-:|:-:|:-:|
25
+ ||[**on_success**](https://differencialx.github.io/decouplio.github.io/on_success/)|[**on_success**](https://differencialx.github.io/decouplio.github.io/on_success/)||[**on_success**](https://differencialx.github.io/decouplio.github.io/on_success/)|[**on_success**](https://differencialx.github.io/decouplio.github.io/on_success/)|-|
26
+ ||[**on_failure**](https://differencialx.github.io/decouplio.github.io/on_failure/)|[**on_failure**](https://differencialx.github.io/decouplio.github.io/on_failure/)||[**on_failure**](https://differencialx.github.io/decouplio.github.io/on_failure/)|[**on_failure**](https://differencialx.github.io/decouplio.github.io/on_failure/)|-|
27
+ ||[**on_error**](https://differencialx.github.io/decouplio.github.io/on_error/)|[**on_error**](https://differencialx.github.io/decouplio.github.io/on_error/)|[**on_error**](https://differencialx.github.io/decouplio.github.io/on_error/)|[**on_error**](https://differencialx.github.io/decouplio.github.io/on_error/)|[**on_error**](https://differencialx.github.io/decouplio.github.io/on_error/)|-|
28
+ ||[**finish_him**](https://differencialx.github.io/decouplio.github.io/finish_him/)|[**finish_him**](https://differencialx.github.io/decouplio.github.io/finish_him/)|[**finish_him**](https://differencialx.github.io/decouplio.github.io/finish_him/)|[**finish_him**](https://differencialx.github.io/decouplio.github.io/finish_him/)||-|
29
+ ||[**if/unless**](https://differencialx.github.io/decouplio.github.io/if_unless/)|[**if/unless**](https://differencialx.github.io/decouplio.github.io/if_unless/)|[**if/unless**](https://differencialx.github.io/decouplio.github.io/if_unless/)|[**if/unless**](https://differencialx.github.io/decouplio.github.io/if_unless/)|[**if/unless**](https://differencialx.github.io/decouplio.github.io/if_unless/)|-|
30
+
31
+ #### [Documentation is HERE](https://differencialx.github.io/decouplio.github.io/)
32
+
33
+ # Quick start
34
+ ## What should you know before start?
35
+
36
+ ### Action
37
+
38
+ Action is a class which encapsulates business logic. To create one just create a class and inherit it from `Decouplio::Action` class
8
39
 
9
40
  ```ruby
10
- gem 'decouplio'
41
+ require 'decouplio'
42
+
43
+ class MyAction < Decouplio::Action
44
+ end
11
45
  ```
12
46
 
13
- And then execute:
47
+ ### Logic block
14
48
 
15
- $ bundle
49
+ Block inside `Action` which contains definition of business logic.
16
50
 
17
- Or install it by yourself:
51
+ ```ruby
52
+ require 'decouplio'
18
53
 
19
- $ gem install decouplio
54
+ class MyAction < Decouplio::Action
55
+ logic do
56
+ # logic block
57
+ end
58
+ end
59
+ ```
20
60
 
21
- ## Currently decouplio is in alpha testing, more features will come soon.
61
+ ### Step
22
62
 
23
- ### Compatibility
24
- Ruby:
25
- - 2.7
26
- - 3.0
63
+ Step is an atomic part of business logic and it defines inside `Logic block`.
64
+
65
+ ```ruby
66
+ require 'decouplio'
67
+
68
+ class MyAction < Decouplio::Action
69
+ logic do
70
+ step :hello_world
71
+ end
72
+
73
+ def hello_world
74
+ ctx[:result] = 'Hello world'
75
+ end
76
+ end
77
+
78
+ MyAction.call[:result] # => Hello world
79
+ ```
80
+
81
+ |Step types|
82
+ |:-:|
83
+ |[**step**](https://differencialx.github.io/decouplio.github.io/step/)|
84
+ |[**fail**](https://differencialx.github.io/decouplio.github.io/fail/)|
85
+ |[**pass**](https://differencialx.github.io/decouplio.github.io/pass/)|
86
+ |[**wrap**](https://differencialx.github.io/decouplio.github.io/wrap/)|
87
+ |[**octo**](https://differencialx.github.io/decouplio.github.io/octo/)|
88
+ |[**resq**](https://differencialx.github.io/decouplio.github.io/resq/)|
89
+
90
+
91
+ ### Context
92
+ Action context is an object which is used to share data between steps. It's accessible only inside step.
93
+ - To access the action context inside step you need to call `ctx` method
94
+ - `ctx` behaves like a `Hash`.
95
+ - To assign some value to `ctx` just do `ctx[:some_key] = 'some value'`
96
+ - To access `ctx` value use `ctx[:some_value]` or use a shortcut `c.some_value`
97
+
98
+ NOTE: you **can't** assign context value using `c.<some key>` shortcut.
99
+
100
+ ```ruby
101
+ require 'decouplio'
102
+
103
+ class CtxIntroduction < Decouplio::Action
104
+ logic do
105
+ step :calculate_result
106
+ end
107
+
108
+ def calculate_result
109
+ ctx[:result] = c.one + c.two
110
+ # OR
111
+ # c[:result] = c[:one] + c[:two]
112
+ #OR
113
+ # ctx[:result] = ctx[:one] + ctx[:two]
114
+ end
115
+ end
116
+
117
+ action_result = CtxIntroduction.call(one: 1, two: 2)
118
+
119
+ action_result[:result] # => 3
120
+ ```
121
+
122
+ ### Success/Failure track
123
+ Execution flow of action is changing depending on step result.
124
+ - If step returns truthy value(**not** `nil|false`), when next `success` track step will be executed.
125
+ - If step returns falsy value(`nil|false`), when next `failure` track step will be executed.
126
+
127
+ |Success track|Failure track|
128
+ |-|-|
129
+ |[**step**](https://differencialx.github.io/decouplio.github.io/step/)|[**fail**](https://differencialx.github.io/decouplio.github.io/fail/)|
130
+ |[**pass**](https://differencialx.github.io/decouplio.github.io/pass/)||
131
+ |[**wrap**](https://differencialx.github.io/decouplio.github.io/wrap/)||
132
+ |[**octo**](https://differencialx.github.io/decouplio.github.io/octo/)||
133
+
134
+ ```ruby
135
+ require 'decouplio'
136
+
137
+ class Divider < Decouplio::Action
138
+ logic do
139
+ step :validate_divider
140
+ step :divide
141
+ fail :failure_message
142
+ end
143
+
144
+ def validate_divider
145
+ !ctx[:divider].zero?
146
+ end
147
+
148
+ def divide
149
+ ctx[:result] = c.number / c.divider
150
+ end
27
151
 
28
- ### [Documentation is HERE](https://differencialx.github.io/decouplio.github.io/)
152
+ def failure_message
153
+ ctx[:error_message] = 'Division by zero is not allowed'
154
+ end
155
+ end
156
+
157
+ divider_success = Divider.call(number: 4, divider: 2)
158
+ divider_success.success? # => true
159
+ divider_success.failure? # => false
160
+ divider_success[:result] # => 2
161
+ divider_success[:error_message] # => nil
162
+ divider_success.railway_flow # => [:validate_divider, :divide]
163
+ puts divider_success # =>
164
+ # Result: success
165
+
166
+ # RailwayFlow:
167
+ # validate_divider -> divide
168
+
169
+ # Context:
170
+ # :number => 4
171
+ # :divider => 2
172
+ # :result => 2
173
+
174
+ # Status: NONE
175
+
176
+ # Errors:
177
+ # NONE
178
+
179
+ divider_failure = Divider.call(number: 4, divider: 0)
180
+ divider_failure.success? #=> false
181
+ divider_failure.failure? #=> true
182
+ divider_failure[:result] # => nil
183
+ divider_failure[:error_message] # => 'Division by zero is not allowed'
184
+ divider_failure.railway_flow# => [:validate_divider, :failure_message]
185
+ divider_failure # =>
186
+ # Result: failure
187
+
188
+ # RailwayFlow:
189
+ # validate_divider -> failure_message
190
+
191
+ # Context:
192
+ # :number => 4
193
+ # :divider => 0
194
+ # :error_message => "Division by zero is not allowed"
195
+
196
+ # Status: NONE
197
+
198
+ # Errors:
199
+ # NONE
200
+
201
+ ```
202
+
203
+ ### Railway flow
204
+
205
+ During execution `Decouplio` is recording executed steps, so you check which steps were executed. It becomes in handy during debugging and writing test.
206
+
207
+ ```ruby
208
+ class RailwayAction < Decouplio::Action
209
+ logic do
210
+ step :step1
211
+ step :step2
212
+ step :step3
213
+ end
214
+
215
+ def step1
216
+ ctx[:step1] = 'Step1'
217
+ end
218
+
219
+ def step2
220
+ ctx[:step2] = 'Step2'
221
+ end
222
+
223
+ def step3
224
+ ctx[:step3] = 'Step3'
225
+ end
226
+ end
227
+
228
+ railway_action = RailwayAction.call
229
+ railway_action.railway_flow.inspect # => [:step1, :step2, :step3]
230
+
231
+ railway_action # =>
232
+ # Result: success
233
+
234
+ # RailwayFlow:
235
+ # step1 -> step2 -> step3
236
+
237
+ # Context:
238
+ # :step1 => "Step1"
239
+ # :step2 => "Step2"
240
+ # :step3 => "Step3"
241
+
242
+ # Status: NONE
243
+
244
+ # Errors:
245
+ # NONE
246
+ ```
247
+
248
+ ### Meta Store
249
+
250
+ Generally `metastore` is a PORO, which is accessible inside steps by calling `meta_store` method or it's alias `ms`. It was created to help developers to standardize things and keep meta info about action, because sometimes `success?` or `failure?` is not enough to make a decision about what to do next. I defined default metastore class which can manage custom action `status` and standardizes the way how error messages should be added.
251
+
252
+ That's how default `metastore` class looks like
253
+ ```ruby
254
+ # frozen_string_literal: true
255
+ module Decouplio
256
+ class DefaultMetaStore
257
+ attr_accessor :status, :errors
258
+
259
+ def initialize
260
+ @errors = {}
261
+ @status = nil
262
+ end
263
+
264
+ def add_error(key, messages)
265
+ @errors.store(
266
+ key,
267
+ (@errors[key] || []) + [messages].flatten
268
+ )
269
+ end
270
+
271
+ # This method is used to print metastore status to console
272
+ # when you checking action output
273
+ def to_s
274
+ <<~METASTORE
275
+ Status: #{@status || 'NONE'}
276
+
277
+ Errors:
278
+ #{errors_string}
279
+ METASTORE
280
+ end
281
+
282
+ private
283
+
284
+ def errors_string
285
+ return 'NONE' if @errors.empty?
286
+
287
+ @errors.map do |k, v|
288
+ "#{k.inspect} => #{v.inspect}"
289
+ end.join("\n ")
290
+ end
291
+ end
292
+ end
293
+ ```
294
+ So it's allows you do this
295
+ ```ruby
296
+ class MetaStoreAction < Decouplio::Action
297
+ logic do
298
+ step :always_fails
299
+ fail :handle_fail
300
+ end
301
+
302
+ # Decouplio has to constants which are accessible inside steps
303
+ # PASS = true
304
+ # FAIL = false
305
+ # You can use then to force step to fail or pass instead of `true` of `false`
306
+
307
+ def always_fails
308
+ FAIL
309
+ end
310
+
311
+ def handle_fail
312
+ ms.status = :failed_and_i_duno_why
313
+ ms.add_error(:something_went_wrong, 'Something went wrong')
314
+ ms.add_error(:something_went_wrong, 'And I duno why :(')
315
+ end
316
+ end
317
+
318
+ MetaStoreAction.call #=>
319
+ # Result: failure
320
+ # RailwayFlow:
321
+ # always_fails -> handle_fail
322
+ # Context:
323
+ # Empty
324
+ # Status: :failed_and_i_duno_why
325
+ # Errors:
326
+ # :something_went_wrong => ["Something went wrong", "And I duno why :("]
327
+ ```
328
+ **NOTE: you can always define your own metastore class accordingly to your needs. [DOCS ARE HERE](https://differencialx.github.io/decouplio.github.io/meta_store/)**
29
329
 
30
330
  ## Contributing
31
331
 
32
332
  Bug reports and pull requests are welcome on GitHub at https://github.com/differencialx/decouplio/issues.
33
333
 
34
- More detailed description for contribution process will be added later.
35
-
36
334
  ## License
37
335
 
38
336
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/decouplio.gemspec CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
17
17
 
18
18
  if spec.respond_to?(:metadata)
19
19
  spec.metadata['homepage_uri'] = spec.homepage
20
- spec.metadata['source_code_uri'] = 'https://github.com/differencialx/decouplio/blob/master/docs'
20
+ spec.metadata['source_code_uri'] = 'https://github.com/differencialx/decouplio/'
21
21
  spec.metadata['changelog_uri'] = 'https://github.com/differencialx/decouplio/blob/master/docs/CHANGELOG.md'
22
22
  else
23
23
  raise 'RubyGems 2.0 or newer is required to protect against ' \
@@ -25,8 +25,14 @@ Gem::Specification.new do |spec|
25
25
  end
26
26
 
27
27
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
28
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
28
+ `git ls-files -z`.split("\x0").select { |f| f.match(%r{^(lib)/|.gemspec|LICENSE|Rakefile|README}) }
29
29
  end
30
+
31
+ # spec.files = Dir.chdir(File.expand_path(__dir__)) do
32
+ # `git ls-files -z`.split("\x0").reject do |f|
33
+ # f.match(%r{(test|spec|features|benchmarks|bin|.rubocop|.gitignore|Dockerfile|.ruby-version|docker|.vscode|.circle)(\/)*})
34
+ # end
35
+ # end
30
36
  spec.bindir = 'exe'
31
37
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
38
  spec.require_paths = ['lib']
@@ -1,52 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'forwardable'
4
- require_relative 'flow'
5
- require_relative 'processor'
6
- require_relative 'default_meta_store'
7
- require_relative 'action_state_printer'
8
- require_relative 'errors/logic_redefinition_error'
9
- require_relative 'errors/logic_is_not_defined_error'
10
- require_relative 'errors/execution_error'
11
- require_relative 'const/results'
12
-
13
3
  module Decouplio
14
4
  class Action
5
+ extend Forwardable
6
+ def_delegator :@ctx, :[]
7
+
15
8
  attr_reader :railway_flow, :ctx, :meta_store
9
+ attr_writer :success
16
10
 
17
11
  alias ms meta_store
12
+ alias c ctx
13
+
14
+ PASS = true
15
+ FAIL = false
18
16
 
19
17
  def initialize(
20
- parent_railway_flow: nil, parent_ctx: nil, meta_store:, **params
18
+ meta_store, parent_railway_flow, ctx
21
19
  )
22
20
  @meta_store = meta_store
23
- @ctx = parent_ctx || params
24
- @railway_flow = parent_railway_flow || []
25
- @failure = false
26
- end
27
-
28
- def [](key)
29
- @ctx[key]
21
+ @ctx = ctx
22
+ @railway_flow = parent_railway_flow
23
+ @success = true
30
24
  end
31
25
 
32
26
  def success?
33
- !@failure
27
+ @success
34
28
  end
35
29
 
36
30
  def failure?
37
- @failure
38
- end
39
-
40
- def fail_action
41
- @failure = true
42
- end
43
-
44
- def pass_action
45
- @failure = false
46
- end
47
-
48
- def append_railway_flow(stp)
49
- railway_flow << stp
31
+ !@success
50
32
  end
51
33
 
52
34
  def inspect
@@ -64,13 +46,15 @@ module Decouplio
64
46
  self.meta_store = klass
65
47
  end
66
48
 
67
- def call(**params)
49
+ def call(_parent_meta_store: nil, _parent_railway_flow: nil, _parent_ctx: nil, **params)
68
50
  instance = new(
69
- **{
70
- meta_store: meta_store.new
71
- }.merge(**params)
51
+ _parent_meta_store || meta_store.new,
52
+ _parent_railway_flow || [],
53
+ _parent_ctx || Ctx[params]
72
54
  )
73
- Decouplio::Processor.call(instance: instance, **@flow)
55
+ next_step = @first_step
56
+
57
+ next_step = next_step.process(instance) while next_step
74
58
  instance
75
59
  end
76
60
 
@@ -92,15 +76,15 @@ module Decouplio
92
76
  end
93
77
 
94
78
  def logic(&block)
95
- if @flow && !@flow[:first_step].nil?
79
+ unless @first_step.nil?
96
80
  raise Decouplio::Errors::LogicRedefinitionError.new(
97
81
  errored_option: to_s
98
82
  )
99
83
  end
100
84
  if block_given?
101
- @flow = Decouplio::Flow.call(logic: block, action_class: self)
85
+ @first_step = Decouplio::NewFlow.call(block)
102
86
 
103
- if @flow && @flow[:first_step].nil?
87
+ if @first_step.nil?
104
88
  raise Decouplio::Errors::LogicIsNotDefinedError.new(
105
89
  errored_option: to_s
106
90
  )
@@ -4,17 +4,12 @@ module Decouplio
4
4
  class ActionStatePrinter
5
5
  def self.call(action)
6
6
  <<~INSPECT
7
-
8
7
  Result: #{result(action)}
9
-
10
8
  RailwayFlow:
11
9
  #{railway_flow(action)}
12
-
13
10
  Context:
14
11
  #{action_context(action)}
15
-
16
12
  #{meta_store(action)}
17
-
18
13
  INSPECT
19
14
  end
20
15
 
@@ -27,6 +22,8 @@ module Decouplio
27
22
  end
28
23
 
29
24
  def self.action_context(action)
25
+ return 'Empty' if action.ctx.empty?
26
+
30
27
  action.ctx.map { |k, v| "#{k.inspect} => #{v.inspect}" }.join("\n ")
31
28
  end
32
29
 
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decouplio
4
+ module Const
5
+ module Flows
6
+ MAIN_FLOW = [
7
+ Decouplio::Steps::Step,
8
+ Decouplio::Steps::Fail,
9
+ Decouplio::Steps::Pass,
10
+ Decouplio::Steps::InnerActionStep,
11
+ Decouplio::Steps::InnerActionFail,
12
+ Decouplio::Steps::InnerActionPass,
13
+ Decouplio::Steps::OctoByKey,
14
+ Decouplio::Steps::OctoByMethod,
15
+ Decouplio::Steps::ServiceAsStep,
16
+ Decouplio::Steps::ServiceAsFail,
17
+ Decouplio::Steps::ServiceAsPass,
18
+ Decouplio::Steps::ServiceAsPass,
19
+ Decouplio::Steps::WrapWithClass,
20
+ Decouplio::Steps::WrapWithClassMethod,
21
+ Decouplio::Steps::Wrap
22
+ ].freeze
23
+ PASS_FLOW = [
24
+ Decouplio::Steps::Step,
25
+ Decouplio::Steps::Pass,
26
+ Decouplio::Steps::InnerActionStep,
27
+ Decouplio::Steps::InnerActionPass,
28
+ Decouplio::Steps::ServiceAsStep,
29
+ Decouplio::Steps::ServiceAsPass,
30
+ Decouplio::Steps::ServiceAsPass,
31
+ Decouplio::Steps::OctoByKey,
32
+ Decouplio::Steps::OctoByMethod,
33
+ Decouplio::Steps::WrapWithClass,
34
+ Decouplio::Steps::WrapWithClassMethod,
35
+ Decouplio::Steps::Wrap
36
+ ].freeze
37
+ FAIL_FLOW = [
38
+ Decouplio::Steps::Fail,
39
+ Decouplio::Steps::InnerActionFail,
40
+ Decouplio::Steps::ServiceAsFail
41
+ ].freeze
42
+ RESQ_CLASSES = [
43
+ Decouplio::Steps::ResqPass,
44
+ Decouplio::Steps::ResqFail,
45
+ Decouplio::Steps::ResqWithMappingPass,
46
+ Decouplio::Steps::ResqWithMappingFail
47
+ ].freeze
48
+ WRAP_CLASSES = [
49
+ Decouplio::Steps::WrapWithClass,
50
+ Decouplio::Steps::WrapWithClassMethod,
51
+ Decouplio::Steps::Wrap
52
+ ].freeze
53
+ OCTO_CLASSES = [
54
+ Decouplio::Steps::OctoByMethod,
55
+ Decouplio::Steps::OctoByKey
56
+ ].freeze
57
+ end
58
+ end
59
+ end
@@ -1,21 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'results'
4
-
5
3
  module Decouplio
6
4
  module Const
7
5
  module ReservedMethods
8
- NAMES = [
9
- :[],
10
- :success?,
11
- :failure?,
12
- :fail_action,
13
- :pass_action,
14
- :append_railway_flow,
15
- :inspect,
16
- :to_s,
17
- Decouplio::Const::Results::STEP_PASS,
18
- Decouplio::Const::Results::STEP_FAIL
6
+ NAMES = %i[
7
+ \[\]
8
+ inspect
9
+ to_s
10
+ PASS
11
+ FAIL
19
12
  ].freeze
20
13
  end
21
14
  end