functional-light-service 6.2.0 → 6.3.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.
Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/lib/functional-light-service.rb +6 -36
  3. metadata +14 -307
  4. data/.github/workflows/project-build.yml +0 -71
  5. data/.gitignore +0 -24
  6. data/.rspec +0 -3
  7. data/.rubocop.yml +0 -101
  8. data/.solargraph.yml +0 -11
  9. data/AUDIT-functional-light-service.md +0 -352
  10. data/Appraisals +0 -7
  11. data/CHANGELOG.md +0 -292
  12. data/CODE_OF_CONDUCT.md +0 -22
  13. data/Gemfile +0 -4
  14. data/LICENSE +0 -22
  15. data/README.md +0 -1663
  16. data/Rakefile +0 -12
  17. data/VERSION +0 -1
  18. data/audit/bench.rb +0 -99
  19. data/audit/verify_findings.rb +0 -172
  20. data/functional-light-service.gemspec +0 -35
  21. data/gemfiles/dry_inflector_0_2_1.gemfile +0 -5
  22. data/gemfiles/i18n_1_8_11.gemfile +0 -5
  23. data/lib/functional-light-service/action.rb +0 -145
  24. data/lib/functional-light-service/configuration.rb +0 -36
  25. data/lib/functional-light-service/context/key_verifier.rb +0 -124
  26. data/lib/functional-light-service/context.rb +0 -208
  27. data/lib/functional-light-service/deprecations.rb +0 -26
  28. data/lib/functional-light-service/errors.rb +0 -9
  29. data/lib/functional-light-service/functional/enum.rb +0 -286
  30. data/lib/functional-light-service/functional/maybe.rb +0 -21
  31. data/lib/functional-light-service/functional/monad.rb +0 -77
  32. data/lib/functional-light-service/functional/null.rb +0 -88
  33. data/lib/functional-light-service/functional/option.rb +0 -100
  34. data/lib/functional-light-service/functional/result.rb +0 -129
  35. data/lib/functional-light-service/functional/sequencer.rb +0 -144
  36. data/lib/functional-light-service/i18n/localization_adapter.rb +0 -50
  37. data/lib/functional-light-service/localization_adapter.rb +0 -39
  38. data/lib/functional-light-service/localization_map.rb +0 -9
  39. data/lib/functional-light-service/organizer/execute.rb +0 -16
  40. data/lib/functional-light-service/organizer/iterate.rb +0 -30
  41. data/lib/functional-light-service/organizer/reduce_case.rb +0 -50
  42. data/lib/functional-light-service/organizer/reduce_if.rb +0 -19
  43. data/lib/functional-light-service/organizer/reduce_if_else.rb +0 -23
  44. data/lib/functional-light-service/organizer/reduce_until.rb +0 -22
  45. data/lib/functional-light-service/organizer/reduce_while.rb +0 -31
  46. data/lib/functional-light-service/organizer/scoped_reducable.rb +0 -15
  47. data/lib/functional-light-service/organizer/with_callback.rb +0 -28
  48. data/lib/functional-light-service/organizer/with_reducer.rb +0 -81
  49. data/lib/functional-light-service/organizer/with_reducer_factory.rb +0 -20
  50. data/lib/functional-light-service/organizer/with_reducer_log_decorator.rb +0 -111
  51. data/lib/functional-light-service/organizer.rb +0 -129
  52. data/lib/functional-light-service/testing/context_factory.rb +0 -48
  53. data/lib/functional-light-service/testing.rb +0 -3
  54. data/lib/functional-light-service/version.rb +0 -5
  55. data/resources/fail_actions.png +0 -0
  56. data/resources/light-service.png +0 -0
  57. data/resources/organizer_and_actions.png +0 -0
  58. data/resources/skip_actions.png +0 -0
  59. data/spec/acceptance/add_numbers_spec.rb +0 -11
  60. data/spec/acceptance/after_actions_spec.rb +0 -87
  61. data/spec/acceptance/around_each_spec.rb +0 -19
  62. data/spec/acceptance/before_actions_spec.rb +0 -115
  63. data/spec/acceptance/custom_log_from_organizer_spec.rb +0 -61
  64. data/spec/acceptance/deprecation_warnings_spec.rb +0 -82
  65. data/spec/acceptance/fail_spec.rb +0 -52
  66. data/spec/acceptance/log_from_organizer_spec.rb +0 -154
  67. data/spec/acceptance/message_localization_spec.rb +0 -119
  68. data/spec/acceptance/organizer/add_aliases_spec.rb +0 -28
  69. data/spec/acceptance/organizer/add_to_context_spec.rb +0 -54
  70. data/spec/acceptance/organizer/around_each_with_reduce_if_spec.rb +0 -42
  71. data/spec/acceptance/organizer/context_failure_and_skipping_spec.rb +0 -90
  72. data/spec/acceptance/organizer/execute_spec.rb +0 -67
  73. data/spec/acceptance/organizer/iterate_spec.rb +0 -44
  74. data/spec/acceptance/organizer/reduce_case_spec.rb +0 -65
  75. data/spec/acceptance/organizer/reduce_if_else_spec.rb +0 -60
  76. data/spec/acceptance/organizer/reduce_if_spec.rb +0 -89
  77. data/spec/acceptance/organizer/reduce_until_spec.rb +0 -49
  78. data/spec/acceptance/organizer/reduce_while_spec.rb +0 -96
  79. data/spec/acceptance/organizer/with_callback_spec.rb +0 -113
  80. data/spec/acceptance/organizer_entry_point_spec.rb +0 -35
  81. data/spec/acceptance/rollback_spec.rb +0 -183
  82. data/spec/acceptance/skip_all_remaining_spec.rb +0 -139
  83. data/spec/acceptance/testing/context_factory_spec.rb +0 -54
  84. data/spec/action_expected_keys_spec.rb +0 -63
  85. data/spec/action_expects_and_promises_spec.rb +0 -97
  86. data/spec/action_optional_expected_keys_spec.rb +0 -107
  87. data/spec/action_promised_keys_spec.rb +0 -126
  88. data/spec/action_spec.rb +0 -97
  89. data/spec/context/inspect_spec.rb +0 -52
  90. data/spec/context_spec.rb +0 -301
  91. data/spec/examples/amount_spec.rb +0 -77
  92. data/spec/examples/controller_spec.rb +0 -63
  93. data/spec/examples/validate_address_spec.rb +0 -38
  94. data/spec/i18n_localization_adapter_spec.rb +0 -83
  95. data/spec/lib/deterministic/class_mixin_spec.rb +0 -24
  96. data/spec/lib/deterministic/currify_spec.rb +0 -90
  97. data/spec/lib/deterministic/monad_axioms.rb +0 -46
  98. data/spec/lib/deterministic/monad_spec.rb +0 -47
  99. data/spec/lib/deterministic/null_spec.rb +0 -65
  100. data/spec/lib/deterministic/option_spec.rb +0 -140
  101. data/spec/lib/deterministic/result/failure_spec.rb +0 -65
  102. data/spec/lib/deterministic/result/result_map_spec.rb +0 -155
  103. data/spec/lib/deterministic/result/result_shared.rb +0 -25
  104. data/spec/lib/deterministic/result/success_spec.rb +0 -41
  105. data/spec/lib/deterministic/result_spec.rb +0 -63
  106. data/spec/lib/deterministic/sequencer_spec.rb +0 -506
  107. data/spec/lib/edge_cases_spec.rb +0 -156
  108. data/spec/lib/enum_spec.rb +0 -114
  109. data/spec/lib/native_pattern_matching_spec.rb +0 -74
  110. data/spec/localization_adapter_spec.rb +0 -66
  111. data/spec/organizer/with_reducer_spec.rb +0 -56
  112. data/spec/organizer_key_aliases_spec.rb +0 -29
  113. data/spec/organizer_spec.rb +0 -115
  114. data/spec/readme_spec.rb +0 -45
  115. data/spec/sample/calculates_order_tax_action_spec.rb +0 -16
  116. data/spec/sample/calculates_tax_spec.rb +0 -30
  117. data/spec/sample/looks_up_tax_percentage_action_spec.rb +0 -55
  118. data/spec/sample/provides_free_shipping_action_spec.rb +0 -25
  119. data/spec/sample/tax/calculates_order_tax_action.rb +0 -10
  120. data/spec/sample/tax/calculates_tax.rb +0 -11
  121. data/spec/sample/tax/looks_up_tax_percentage_action.rb +0 -28
  122. data/spec/sample/tax/provides_free_shipping_action.rb +0 -11
  123. data/spec/spec_helper.rb +0 -32
  124. data/spec/support.rb +0 -1
  125. data/spec/test_doubles.rb +0 -656
  126. data/spec/testing/context_factory/iterate_spec.rb +0 -39
  127. data/spec/testing/context_factory/reduce_if_spec.rb +0 -40
  128. data/spec/testing/context_factory/reduce_until_spec.rb +0 -40
  129. data/spec/testing/context_factory/with_callback_spec.rb +0 -38
  130. data/spec/testing/context_factory_spec.rb +0 -76
@@ -1,100 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FunctionalLightService
4
- Option = FunctionalLightService.enum do
5
- Some(:s)
6
- None()
7
- end
8
-
9
- class Option
10
- class Some
11
- def initialize(init)
12
- raise ArgumentError, "Some cannot wrap nil: use None instead" if init.nil?
13
-
14
- super
15
- end
16
- end
17
-
18
- class << self
19
- def some?(expr)
20
- to_option(expr) { expr.nil? }
21
- end
22
-
23
- def any?(expr)
24
- to_option(expr) { expr.nil? || (expr.respond_to?(:empty?) && expr.empty?) }
25
- end
26
-
27
- def to_option(expr)
28
- yield(expr) ? None.new : Some.new(expr)
29
- end
30
-
31
- def try!
32
- yield
33
- rescue StandardError
34
- None.new
35
- end
36
- end
37
- end
38
-
39
- # Le operazioni usano il dispatch diretto invece del motore match:
40
- # stessa semantica, ~2 ordini di grandezza piu veloce (audit, finding 3.1)
41
- impl(Option) do
42
- def fmap
43
- some? ? self.class.new(yield(@value)) : self
44
- end
45
-
46
- def map(&fn)
47
- some? ? bind(&fn) : self
48
- end
49
-
50
- def some?
51
- is_a? Option::Some
52
- end
53
-
54
- def none?
55
- is_a? Option::None
56
- end
57
-
58
- alias :empty? :none?
59
-
60
- def value_or(n)
61
- some? ? @value : n
62
- end
63
-
64
- def value_to_a
65
- @value
66
- end
67
-
68
- def +(other)
69
- FunctionalLightService::Deprecations.warn(
70
- "Option#+ is deprecated and will be removed in a future release; " \
71
- "combine the two options explicitly"
72
- )
73
- return other if none?
74
- raise TypeError, "Other must be an #{Option}" unless other.is_a?(Option)
75
-
76
- other.some? ? Option::Some.new(@value + other.value) : self
77
- end
78
- end
79
-
80
- module Prelude
81
- module Option
82
- None = FunctionalLightService::Option::None.new
83
- Option = FunctionalLightService::Option
84
- # rubocop:disable Naming/MethodName
85
- def Some(s)
86
- FunctionalLightService::Option::Some.new(s)
87
- end
88
-
89
- def None
90
- FunctionalLightService::Prelude::Option::None
91
- end
92
-
93
- def Option
94
- FunctionalLightService::Option
95
- end
96
- # rubocop:enable Naming/MethodName
97
- # include Option
98
- end
99
- end
100
- end
@@ -1,129 +0,0 @@
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,144 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'delegate'
4
-
5
- module FunctionalLightService
6
- # Do-notation for Result: chains steps that return Success/Failure,
7
- # short-circuiting on the first Failure. Ported from the deterministic
8
- # gem (MIT License, Copyright (c) Piotr Zolnierek and contributors,
9
- # https://github.com/pzol/deterministic).
10
- #
11
- # in_sequence do
12
- # get(:user) { fetch_user(id) } # binds the Success value to :user
13
- # let(:name) { user.fetch(:name) } # binds a plain (non-Result) value
14
- # and_then { validate(user) } # step without binding
15
- # observe { log(name) } # side effect, return value ignored
16
- # and_yield { Success(name) } # final result of the sequence
17
- # end
18
- module Sequencer
19
- class InvalidSequenceError < StandardError; end
20
-
21
- module Operation
22
- Get = Struct.new(:block, :name)
23
- Let = Struct.new(:block, :name)
24
- AndThen = Struct.new(:block)
25
- Observe = Struct.new(:block)
26
- AndYield = Struct.new(:block)
27
- end
28
-
29
- def in_sequence(&)
30
- sequencer = Sequencer.new(self)
31
- sequencer.instance_eval(&)
32
- sequencer.yield
33
- end
34
-
35
- class Sequencer
36
- def initialize(instance)
37
- @operations = []
38
- @operation_wrapper = OperationWrapper.new(instance)
39
- end
40
-
41
- def get(name, &block)
42
- raise ArgumentError, 'no block given' unless block_given?
43
- raise InvalidSequenceError, 'and_yield already called' if @sequenced_operations
44
-
45
- @operations << Operation::Get.new(block, name)
46
- end
47
-
48
- def let(name, &block)
49
- raise ArgumentError, 'no block given' unless block_given?
50
- raise InvalidSequenceError, 'and_yield already called' if @sequenced_operations
51
-
52
- @operations << Operation::Let.new(block, name)
53
- end
54
-
55
- def and_then(&block)
56
- raise ArgumentError, 'no block given' unless block_given?
57
- raise InvalidSequenceError, 'and_yield already called' if @sequenced_operations
58
-
59
- @operations << Operation::AndThen.new(block)
60
- end
61
-
62
- def observe(&block)
63
- raise ArgumentError, 'no block given' unless block_given?
64
- raise InvalidSequenceError, 'and_yield already called' if @sequenced_operations
65
-
66
- @operations << Operation::Observe.new(block)
67
- end
68
-
69
- def and_yield(&block)
70
- raise ArgumentError, 'no block given' unless block_given?
71
- raise InvalidSequenceError, 'and_yield already called' if @sequenced_operations
72
-
73
- @operations << Operation::AndYield.new(block)
74
-
75
- prepare_sequenced_operations
76
- end
77
-
78
- def yield
79
- raise InvalidSequenceError, 'and_yield not called' unless @sequenced_operations
80
-
81
- @operation_wrapper.instance_eval(&@sequenced_operations)
82
- end
83
-
84
- private
85
-
86
- # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
87
- def prepare_sequenced_operations
88
- operations = @operations
89
-
90
- @sequenced_operations = ->(_) do
91
- operations.reduce(Result::Success.new(nil)) do |last_result, operation|
92
- last_result.map do
93
- case operation
94
- when Operation::Get
95
- result = instance_eval(&operation.block)
96
- result.map do |output|
97
- # Runs in the context of the OperationWrapper, so the
98
- # bound value is stored within the wrapper itself.
99
- @gotten_results[operation.name] = output
100
- result
101
- end
102
- when Operation::Let
103
- @gotten_results[operation.name] = instance_eval(&operation.block)
104
- last_result
105
- when Operation::Observe
106
- instance_eval(&operation.block)
107
- last_result
108
- when Operation::AndThen, Operation::AndYield
109
- instance_eval(&operation.block)
110
- end
111
- end
112
- end
113
- end
114
- end
115
- # rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity
116
- end
117
-
118
- # OperationWrapper proxies all method calls to the wrapped instance, but
119
- # first checks if the name of the called method matches a value stored
120
- # within @gotten_results and returns the value if it does.
121
- class OperationWrapper < SimpleDelegator
122
- def initialize(*args)
123
- super
124
- @gotten_results = {}
125
- end
126
-
127
- def method_missing(name, *args, **kwargs, &)
128
- if @gotten_results.key?(name)
129
- @gotten_results[name]
130
- else
131
- super
132
- end
133
- end
134
-
135
- def respond_to_missing?(name, include_private = false)
136
- @gotten_results.key?(name) || super
137
- end
138
- end
139
- end
140
-
141
- module Prelude
142
- include Sequencer
143
- end
144
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'dry/inflector'
4
-
5
- module FunctionalLightService
6
- module I18n
7
- class LocalizationAdapter
8
- def failure(message_or_key, action_class, i18n_options = {})
9
- find_translated_message(message_or_key,
10
- action_class,
11
- i18n_options,
12
- :type => :failure)
13
- end
14
-
15
- def success(message_or_key, action_class, i18n_options = {})
16
- find_translated_message(message_or_key,
17
- action_class,
18
- i18n_options,
19
- :type => :success)
20
- end
21
-
22
- private
23
-
24
- def find_translated_message(message_or_key,
25
- action_class,
26
- i18n_options,
27
- type)
28
- if message_or_key.is_a?(Symbol)
29
- translate(message_or_key, action_class, i18n_options.merge(type))
30
- else
31
- message_or_key
32
- end
33
- end
34
-
35
- def translate(key, action_class, options = {})
36
- type = options.delete(:type)
37
-
38
- scope = i18n_scope_from_class(action_class, type)
39
- options[:scope] = scope
40
-
41
- ::I18n.t(key, **options)
42
- end
43
-
44
- def i18n_scope_from_class(action_class, type)
45
- inflector = Dry::Inflector.new
46
- "#{inflector.underscore(action_class.name)}.light_service.#{inflector.pluralize(type)}"
47
- end
48
- end
49
- end
50
- end
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'dry/inflector'
4
-
5
- module FunctionalLightService
6
- # Adapter built-in basato su LocalizationMap: nessuna dipendenza da I18n.
7
- # Viene selezionato da Configuration quando la costante ::I18n non esiste
8
- class LocalizationAdapter
9
- INFLECTOR = Dry::Inflector.new
10
-
11
- def failure(message_or_key, action_class, options = {})
12
- find_translated_message(message_or_key,
13
- INFLECTOR.underscore(action_class.to_s),
14
- options.merge(:type => :failures))
15
- end
16
-
17
- def success(message_or_key, action_class, options = {})
18
- find_translated_message(message_or_key,
19
- INFLECTOR.underscore(action_class.to_s),
20
- options.merge(:type => :successes))
21
- end
22
-
23
- private
24
-
25
- def find_translated_message(message_or_key, action_class, options)
26
- if message_or_key.is_a?(Symbol)
27
- FunctionalLightService::LocalizationMap.instance.dig(
28
- FunctionalLightService::Configuration.locale,
29
- action_class.to_sym,
30
- :light_service,
31
- options[:type],
32
- message_or_key
33
- )
34
- else
35
- message_or_key
36
- end
37
- end
38
- end
39
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'singleton'
4
-
5
- module FunctionalLightService
6
- class LocalizationMap < Hash
7
- include ::Singleton
8
- end
9
- end
@@ -1,16 +0,0 @@
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,30 +0,0 @@
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,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FunctionalLightService
4
- module Organizer
5
- class ReduceCase
6
- extend ScopedReducable
7
-
8
- class Arguments
9
- attr_reader :value, :when, :else
10
-
11
- def initialize(**args)
12
- validate_arguments(**args)
13
- @value = args[:value]
14
- @when = args[:when]
15
- @else = args[:else]
16
- end
17
-
18
- private
19
-
20
- # rubocop:disable Style/MultilineIfModifier
21
- def validate_arguments(**args)
22
- raise(
23
- ArgumentError,
24
- "Expected keyword arguments: [:value, :when, :else]. Given: #{args.keys}"
25
- ) unless args.keys.intersection(mandatory_arguments).count == mandatory_arguments.count
26
- end
27
- # rubocop:enable Style/MultilineIfModifier
28
-
29
- def mandatory_arguments
30
- %i[value when else]
31
- end
32
- end
33
-
34
- def self.run(organizer, **args)
35
- arguments = Arguments.new(**args)
36
-
37
- ->(ctx) do
38
- return ctx if ctx.stop_processing?
39
-
40
- matched_case = arguments.when.keys.find { |k| k.eql?(ctx[arguments.value]) }
41
- steps = arguments.when[matched_case] || arguments.else
42
-
43
- ctx = scoped_reduce(organizer, ctx, steps)
44
-
45
- ctx
46
- end
47
- end
48
- end
49
- end
50
- end
@@ -1,19 +0,0 @@
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,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FunctionalLightService
4
- module Organizer
5
- class ReduceIfElse
6
- extend ScopedReducable
7
-
8
- def self.run(organizer, condition_block, if_steps, else_steps)
9
- ->(ctx) do
10
- return ctx if ctx.stop_processing?
11
-
12
- ctx = if condition_block.call(ctx)
13
- scoped_reduce(organizer, ctx, if_steps)
14
- else
15
- scoped_reduce(organizer, ctx, else_steps)
16
- end
17
-
18
- ctx
19
- end
20
- end
21
- end
22
- end
23
- end
@@ -1,22 +0,0 @@
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.stop_processing?
15
- end
16
-
17
- ctx
18
- end
19
- end
20
- end
21
- end
22
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FunctionalLightService
4
- module Organizer
5
- class ReduceWhile
6
- def self.run(organizer, condition_block, steps)
7
- ->(ctx) do
8
- return ctx if ctx.stop_processing?
9
-
10
- reset_skip(ctx)
11
-
12
- Array(steps).each do |step|
13
- break unless condition_block.call(ctx)
14
-
15
- ctx = organizer.with(ctx).reduce([step])
16
- break if ctx.stop_processing?
17
- end
18
-
19
- reset_skip(ctx)
20
-
21
- ctx
22
- end
23
- end
24
-
25
- def self.reset_skip(ctx)
26
- ctx.reset_skip_remaining! unless ctx.failure? || ctx.skip_all_remaining?
27
- end
28
- private_class_method :reset_skip
29
- end
30
- end
31
- end
@@ -1,15 +0,0 @@
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? || ctx.skip_all_remaining?
8
- ctx = organizer.with(ctx).reduce([steps])
9
- ctx.reset_skip_remaining! unless ctx.failure? || ctx.skip_all_remaining?
10
-
11
- ctx
12
- end
13
- end
14
- end
15
- end