functional-light-service 0.4.4 → 6.0.0
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/.github/workflows/project-build.yml +43 -11
- data/.rubocop.yml +101 -160
- data/AUDIT-functional-light-service.md +352 -0
- data/Appraisals +4 -0
- data/CHANGELOG.md +118 -0
- data/Gemfile +0 -2
- data/README.md +1544 -1426
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/audit/bench.rb +99 -0
- data/audit/verify_findings.rb +172 -0
- data/functional-light-service.gemspec +15 -16
- data/lib/functional-light-service/action.rb +97 -101
- data/lib/functional-light-service/configuration.rb +26 -24
- data/lib/functional-light-service/context/key_verifier.rb +124 -118
- data/lib/functional-light-service/context.rb +63 -20
- data/lib/functional-light-service/deprecations.rb +26 -0
- data/lib/functional-light-service/errors.rb +8 -6
- data/lib/functional-light-service/functional/enum.rb +286 -250
- data/lib/functional-light-service/functional/maybe.rb +21 -15
- data/lib/functional-light-service/functional/monad.rb +77 -66
- data/lib/functional-light-service/functional/null.rb +88 -74
- data/lib/functional-light-service/functional/option.rb +100 -97
- data/lib/functional-light-service/functional/result.rb +129 -116
- data/lib/functional-light-service/localization_adapter.rb +48 -47
- data/lib/functional-light-service/organizer/execute.rb +16 -14
- data/lib/functional-light-service/organizer/iterate.rb +30 -25
- data/lib/functional-light-service/organizer/reduce_if.rb +19 -17
- data/lib/functional-light-service/organizer/reduce_until.rb +22 -20
- data/lib/functional-light-service/organizer/scoped_reducable.rb +15 -13
- data/lib/functional-light-service/organizer/with_callback.rb +28 -26
- data/lib/functional-light-service/organizer/with_reducer.rb +81 -71
- data/lib/functional-light-service/organizer/with_reducer_factory.rb +20 -18
- data/lib/functional-light-service/organizer/with_reducer_log_decorator.rb +110 -105
- data/lib/functional-light-service/organizer.rb +114 -104
- data/lib/functional-light-service/testing/context_factory.rb +48 -42
- data/lib/functional-light-service/testing.rb +3 -1
- data/lib/functional-light-service/version.rb +5 -3
- data/lib/functional-light-service.rb +30 -28
- data/spec/acceptance/after_actions_spec.rb +87 -71
- data/spec/acceptance/before_actions_spec.rb +115 -98
- data/spec/acceptance/custom_log_from_organizer_spec.rb +61 -60
- data/spec/acceptance/deprecation_warnings_spec.rb +82 -0
- data/spec/acceptance/fail_spec.rb +52 -50
- data/spec/acceptance/message_localization_spec.rb +119 -118
- data/spec/acceptance/organizer/add_aliases_spec.rb +28 -0
- data/spec/acceptance/organizer/add_to_context_spec.rb +30 -0
- data/spec/acceptance/organizer/context_failure_and_skipping_spec.rb +68 -65
- data/spec/acceptance/organizer/iterate_spec.rb +7 -0
- data/spec/acceptance/organizer/reduce_if_spec.rb +89 -83
- data/spec/acceptance/organizer/reduce_until_spec.rb +6 -0
- data/spec/acceptance/organizer/with_callback_spec.rb +113 -110
- data/spec/acceptance/{not_having_call_method_warning_spec.rb → organizer_entry_point_spec.rb} +10 -7
- data/spec/acceptance/rollback_spec.rb +183 -132
- data/spec/action_expects_and_promises_spec.rb +97 -93
- data/spec/action_promised_keys_spec.rb +126 -122
- data/spec/action_spec.rb +8 -0
- data/spec/context_spec.rb +289 -197
- data/spec/examples/controller_spec.rb +63 -63
- data/spec/examples/validate_address_spec.rb +38 -37
- data/spec/lib/deterministic/currify_spec.rb +90 -88
- data/spec/lib/deterministic/null_spec.rb +6 -1
- data/spec/lib/deterministic/option_spec.rb +140 -133
- data/spec/lib/deterministic/result/result_map_spec.rb +155 -154
- data/spec/lib/deterministic/result/result_shared.rb +3 -2
- data/spec/lib/deterministic/result_spec.rb +2 -2
- data/spec/lib/edge_cases_spec.rb +156 -0
- data/spec/lib/enum_spec.rb +1 -1
- data/spec/lib/native_pattern_matching_spec.rb +74 -0
- data/spec/organizer_spec.rb +115 -93
- data/spec/readme_spec.rb +45 -47
- data/spec/sample/calculates_order_tax_action_spec.rb +16 -16
- data/spec/sample/calculates_tax_spec.rb +1 -1
- data/spec/sample/looks_up_tax_percentage_action_spec.rb +55 -55
- data/spec/sample/provides_free_shipping_action_spec.rb +1 -1
- data/spec/sample/tax/calculates_order_tax_action.rb +10 -9
- data/spec/sample/tax/looks_up_tax_percentage_action.rb +28 -27
- data/spec/sample/tax/provides_free_shipping_action.rb +11 -10
- data/spec/spec_helper.rb +21 -13
- data/spec/test_doubles.rb +628 -564
- data/spec/testing/context_factory_spec.rb +21 -0
- metadata +49 -117
- data/.travis.yml +0 -24
- data/lib/functional-light-service/organizer/verify_call_method_exists.rb +0 -29
- data/spec/acceptance/include_warning_spec.rb +0 -29
|
@@ -1,116 +1,129 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FunctionalLightService
|
|
4
|
+
Result = FunctionalLightService.enum do
|
|
5
|
+
Success(:s)
|
|
6
|
+
Failure(:f)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
class Result
|
|
10
|
+
class << self
|
|
11
|
+
def try!
|
|
12
|
+
Success.new(yield)
|
|
13
|
+
rescue StandardError => e
|
|
14
|
+
Failure.new(e)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# rubocop:disable Metrics/BlockLength
|
|
20
|
+
FunctionalLightService.impl(Result) do
|
|
21
|
+
def map(proc = nil, &block)
|
|
22
|
+
success? ? bind(proc || block) : self
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
alias :>> :map
|
|
26
|
+
alias :and_then :map
|
|
27
|
+
|
|
28
|
+
def map_err(proc = nil, &block)
|
|
29
|
+
failure? ? bind(proc || block) : self
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
alias :or_else :map_err
|
|
33
|
+
|
|
34
|
+
def pipe(proc = nil, &block)
|
|
35
|
+
(proc || block).call(self)
|
|
36
|
+
self
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def <<(proc = nil, &block)
|
|
40
|
+
FunctionalLightService::Deprecations.warn(
|
|
41
|
+
"Result#<< is deprecated; use #pipe instead"
|
|
42
|
+
)
|
|
43
|
+
pipe(proc, &block)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def success?
|
|
47
|
+
is_a? Result::Success
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def failure?
|
|
51
|
+
is_a? Result::Failure
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Le operazioni usano il dispatch diretto invece del motore match:
|
|
55
|
+
# stessa semantica, ~2 ordini di grandezza piu veloce (audit, finding 3.1)
|
|
56
|
+
def or(other)
|
|
57
|
+
unless other.is_a? Result
|
|
58
|
+
msg = "Expected #{other.inspect} to be a Result"
|
|
59
|
+
raise FunctionalLightService::Monad::NotMonadError, msg
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
success? ? self : other
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def and(other)
|
|
66
|
+
unless other.is_a? Result
|
|
67
|
+
msg = "Expected #{other.inspect} to be a Result"
|
|
68
|
+
raise FunctionalLightService::Monad::NotMonadError, msg
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
success? ? other : self
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def +(other)
|
|
75
|
+
FunctionalLightService::Deprecations.warn(
|
|
76
|
+
"Result#+ is deprecated and will be removed in a future release; " \
|
|
77
|
+
"combine the two results explicitly"
|
|
78
|
+
)
|
|
79
|
+
unless other.is_a? Result
|
|
80
|
+
msg = "Expected #{other.inspect} to be a Result"
|
|
81
|
+
raise FunctionalLightService::Monad::NotMonadError, msg
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
if success? == other.success?
|
|
85
|
+
self.class.new(value + other.value)
|
|
86
|
+
elsif success?
|
|
87
|
+
other # other is the failure
|
|
88
|
+
else
|
|
89
|
+
self # self is the failure
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def try(proc = nil, &block)
|
|
94
|
+
map(proc, &block)
|
|
95
|
+
rescue StandardError => e
|
|
96
|
+
Result::Failure.new(e)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def >=(proc = nil, &block)
|
|
100
|
+
FunctionalLightService::Deprecations.warn(
|
|
101
|
+
"Result#>= is deprecated; use #try instead"
|
|
102
|
+
)
|
|
103
|
+
try(proc, &block)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
# rubocop:enable Metrics/BlockLength
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
module FunctionalLightService
|
|
110
|
+
module Prelude
|
|
111
|
+
module Result
|
|
112
|
+
# rubocop:disable Naming/MethodName
|
|
113
|
+
def try!(&)
|
|
114
|
+
FunctionalLightService::Result.try!(&)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def Success(s)
|
|
118
|
+
FunctionalLightService::Result::Success.new(s)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def Failure(f)
|
|
122
|
+
FunctionalLightService::Result::Failure.new(f)
|
|
123
|
+
end
|
|
124
|
+
# rubocop:enable Naming/MethodName
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
include Result
|
|
128
|
+
end
|
|
129
|
+
end
|
|
@@ -1,47 +1,48 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'i18n'
|
|
4
|
+
|
|
5
|
+
module FunctionalLightService
|
|
6
|
+
class LocalizationAdapter
|
|
7
|
+
def failure(message_or_key, action_class, i18n_options = {})
|
|
8
|
+
find_translated_message(message_or_key,
|
|
9
|
+
action_class,
|
|
10
|
+
i18n_options,
|
|
11
|
+
:type => :failure)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def success(message_or_key, action_class, i18n_options = {})
|
|
15
|
+
find_translated_message(message_or_key,
|
|
16
|
+
action_class,
|
|
17
|
+
i18n_options,
|
|
18
|
+
:type => :success)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def find_translated_message(message_or_key,
|
|
24
|
+
action_class,
|
|
25
|
+
i18n_options,
|
|
26
|
+
type)
|
|
27
|
+
if message_or_key.is_a?(Symbol)
|
|
28
|
+
translate(message_or_key, action_class, i18n_options.merge(type))
|
|
29
|
+
else
|
|
30
|
+
message_or_key
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def translate(key, action_class, options = {})
|
|
35
|
+
type = options.delete(:type)
|
|
36
|
+
|
|
37
|
+
scope = i18n_scope_from_class(action_class, type)
|
|
38
|
+
options[:scope] = scope
|
|
39
|
+
|
|
40
|
+
I18n.t(key, **options)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def i18n_scope_from_class(action_class, type)
|
|
44
|
+
inflector = Dry::Inflector.new
|
|
45
|
+
"#{inflector.underscore(action_class.name)}.light_service.#{inflector.pluralize(type)}"
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FunctionalLightService
|
|
4
|
+
module Organizer
|
|
5
|
+
class Execute
|
|
6
|
+
def self.run(code_block)
|
|
7
|
+
->(ctx) do
|
|
8
|
+
return ctx if ctx.stop_processing?
|
|
9
|
+
|
|
10
|
+
code_block.call(ctx)
|
|
11
|
+
ctx
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -1,25 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
ctx
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "dry/inflector"
|
|
4
|
+
|
|
5
|
+
module FunctionalLightService
|
|
6
|
+
module Organizer
|
|
7
|
+
class Iterate
|
|
8
|
+
extend ScopedReducable
|
|
9
|
+
|
|
10
|
+
INFLECTOR = Dry::Inflector.new
|
|
11
|
+
|
|
12
|
+
def self.run(organizer, collection_key, steps)
|
|
13
|
+
# La singolarizzazione dipende solo dalla chiave: si calcola una volta,
|
|
14
|
+
# non a ogni invocazione dello step (ne' tantomeno per ogni item)
|
|
15
|
+
item_key = INFLECTOR.singularize(collection_key).to_sym
|
|
16
|
+
|
|
17
|
+
->(ctx) do
|
|
18
|
+
return ctx if ctx.stop_processing?
|
|
19
|
+
|
|
20
|
+
ctx[collection_key].each do |item|
|
|
21
|
+
ctx[item_key] = item
|
|
22
|
+
ctx = scoped_reduce(organizer, ctx, steps)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
ctx
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
ctx
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FunctionalLightService
|
|
4
|
+
module Organizer
|
|
5
|
+
class ReduceIf
|
|
6
|
+
extend ScopedReducable
|
|
7
|
+
|
|
8
|
+
def self.run(organizer, condition_block, steps)
|
|
9
|
+
->(ctx) do
|
|
10
|
+
return ctx if ctx.stop_processing?
|
|
11
|
+
|
|
12
|
+
ctx = scoped_reduce(organizer, ctx, steps) if condition_block.call(ctx)
|
|
13
|
+
|
|
14
|
+
ctx
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -1,20 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FunctionalLightService
|
|
4
|
+
module Organizer
|
|
5
|
+
class ReduceUntil
|
|
6
|
+
extend ScopedReducable
|
|
7
|
+
|
|
8
|
+
def self.run(organizer, condition_block, steps)
|
|
9
|
+
->(ctx) do
|
|
10
|
+
return ctx if ctx.stop_processing?
|
|
11
|
+
|
|
12
|
+
loop do
|
|
13
|
+
ctx = scoped_reduce(organizer, ctx, steps)
|
|
14
|
+
break if condition_block.call(ctx) || ctx.failure?
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
ctx
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
ctx.reset_skip_remaining! unless ctx.failure?
|
|
8
|
-
|
|
9
|
-
ctx
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FunctionalLightService
|
|
4
|
+
module Organizer
|
|
5
|
+
module ScopedReducable
|
|
6
|
+
def scoped_reduce(organizer, ctx, steps)
|
|
7
|
+
ctx.reset_skip_remaining! unless ctx.failure?
|
|
8
|
+
ctx = organizer.with(ctx).reduce([steps])
|
|
9
|
+
ctx.reset_skip_remaining! unless ctx.failure?
|
|
10
|
+
|
|
11
|
+
ctx
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -1,26 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
ctx[:callback]
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
ctx
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FunctionalLightService
|
|
4
|
+
module Organizer
|
|
5
|
+
class WithCallback
|
|
6
|
+
extend ScopedReducable
|
|
7
|
+
|
|
8
|
+
def self.run(organizer, action, steps)
|
|
9
|
+
->(ctx) do
|
|
10
|
+
return ctx if ctx.stop_processing?
|
|
11
|
+
|
|
12
|
+
# This will only allow 2 level deep nesting of callbacks
|
|
13
|
+
previous_callback = ctx[:callback]
|
|
14
|
+
|
|
15
|
+
ctx[:callback] = ->(context) do
|
|
16
|
+
ctx = scoped_reduce(organizer, context, steps)
|
|
17
|
+
ctx
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
ctx = action.execute(ctx)
|
|
21
|
+
ctx[:callback] = previous_callback
|
|
22
|
+
|
|
23
|
+
ctx
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|