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.
- checksums.yaml +4 -4
- data/lib/functional-light-service.rb +6 -36
- metadata +14 -307
- data/.github/workflows/project-build.yml +0 -71
- data/.gitignore +0 -24
- data/.rspec +0 -3
- data/.rubocop.yml +0 -101
- data/.solargraph.yml +0 -11
- data/AUDIT-functional-light-service.md +0 -352
- data/Appraisals +0 -7
- data/CHANGELOG.md +0 -292
- data/CODE_OF_CONDUCT.md +0 -22
- data/Gemfile +0 -4
- data/LICENSE +0 -22
- data/README.md +0 -1663
- data/Rakefile +0 -12
- data/VERSION +0 -1
- data/audit/bench.rb +0 -99
- data/audit/verify_findings.rb +0 -172
- data/functional-light-service.gemspec +0 -35
- data/gemfiles/dry_inflector_0_2_1.gemfile +0 -5
- data/gemfiles/i18n_1_8_11.gemfile +0 -5
- data/lib/functional-light-service/action.rb +0 -145
- data/lib/functional-light-service/configuration.rb +0 -36
- data/lib/functional-light-service/context/key_verifier.rb +0 -124
- data/lib/functional-light-service/context.rb +0 -208
- data/lib/functional-light-service/deprecations.rb +0 -26
- data/lib/functional-light-service/errors.rb +0 -9
- data/lib/functional-light-service/functional/enum.rb +0 -286
- data/lib/functional-light-service/functional/maybe.rb +0 -21
- data/lib/functional-light-service/functional/monad.rb +0 -77
- data/lib/functional-light-service/functional/null.rb +0 -88
- data/lib/functional-light-service/functional/option.rb +0 -100
- data/lib/functional-light-service/functional/result.rb +0 -129
- data/lib/functional-light-service/functional/sequencer.rb +0 -144
- data/lib/functional-light-service/i18n/localization_adapter.rb +0 -50
- data/lib/functional-light-service/localization_adapter.rb +0 -39
- data/lib/functional-light-service/localization_map.rb +0 -9
- data/lib/functional-light-service/organizer/execute.rb +0 -16
- data/lib/functional-light-service/organizer/iterate.rb +0 -30
- data/lib/functional-light-service/organizer/reduce_case.rb +0 -50
- data/lib/functional-light-service/organizer/reduce_if.rb +0 -19
- data/lib/functional-light-service/organizer/reduce_if_else.rb +0 -23
- data/lib/functional-light-service/organizer/reduce_until.rb +0 -22
- data/lib/functional-light-service/organizer/reduce_while.rb +0 -31
- data/lib/functional-light-service/organizer/scoped_reducable.rb +0 -15
- data/lib/functional-light-service/organizer/with_callback.rb +0 -28
- data/lib/functional-light-service/organizer/with_reducer.rb +0 -81
- data/lib/functional-light-service/organizer/with_reducer_factory.rb +0 -20
- data/lib/functional-light-service/organizer/with_reducer_log_decorator.rb +0 -111
- data/lib/functional-light-service/organizer.rb +0 -129
- data/lib/functional-light-service/testing/context_factory.rb +0 -48
- data/lib/functional-light-service/testing.rb +0 -3
- data/lib/functional-light-service/version.rb +0 -5
- data/resources/fail_actions.png +0 -0
- data/resources/light-service.png +0 -0
- data/resources/organizer_and_actions.png +0 -0
- data/resources/skip_actions.png +0 -0
- data/spec/acceptance/add_numbers_spec.rb +0 -11
- data/spec/acceptance/after_actions_spec.rb +0 -87
- data/spec/acceptance/around_each_spec.rb +0 -19
- data/spec/acceptance/before_actions_spec.rb +0 -115
- data/spec/acceptance/custom_log_from_organizer_spec.rb +0 -61
- data/spec/acceptance/deprecation_warnings_spec.rb +0 -82
- data/spec/acceptance/fail_spec.rb +0 -52
- data/spec/acceptance/log_from_organizer_spec.rb +0 -154
- data/spec/acceptance/message_localization_spec.rb +0 -119
- data/spec/acceptance/organizer/add_aliases_spec.rb +0 -28
- data/spec/acceptance/organizer/add_to_context_spec.rb +0 -54
- data/spec/acceptance/organizer/around_each_with_reduce_if_spec.rb +0 -42
- data/spec/acceptance/organizer/context_failure_and_skipping_spec.rb +0 -90
- data/spec/acceptance/organizer/execute_spec.rb +0 -67
- data/spec/acceptance/organizer/iterate_spec.rb +0 -44
- data/spec/acceptance/organizer/reduce_case_spec.rb +0 -65
- data/spec/acceptance/organizer/reduce_if_else_spec.rb +0 -60
- data/spec/acceptance/organizer/reduce_if_spec.rb +0 -89
- data/spec/acceptance/organizer/reduce_until_spec.rb +0 -49
- data/spec/acceptance/organizer/reduce_while_spec.rb +0 -96
- data/spec/acceptance/organizer/with_callback_spec.rb +0 -113
- data/spec/acceptance/organizer_entry_point_spec.rb +0 -35
- data/spec/acceptance/rollback_spec.rb +0 -183
- data/spec/acceptance/skip_all_remaining_spec.rb +0 -139
- data/spec/acceptance/testing/context_factory_spec.rb +0 -54
- data/spec/action_expected_keys_spec.rb +0 -63
- data/spec/action_expects_and_promises_spec.rb +0 -97
- data/spec/action_optional_expected_keys_spec.rb +0 -107
- data/spec/action_promised_keys_spec.rb +0 -126
- data/spec/action_spec.rb +0 -97
- data/spec/context/inspect_spec.rb +0 -52
- data/spec/context_spec.rb +0 -301
- data/spec/examples/amount_spec.rb +0 -77
- data/spec/examples/controller_spec.rb +0 -63
- data/spec/examples/validate_address_spec.rb +0 -38
- data/spec/i18n_localization_adapter_spec.rb +0 -83
- data/spec/lib/deterministic/class_mixin_spec.rb +0 -24
- data/spec/lib/deterministic/currify_spec.rb +0 -90
- data/spec/lib/deterministic/monad_axioms.rb +0 -46
- data/spec/lib/deterministic/monad_spec.rb +0 -47
- data/spec/lib/deterministic/null_spec.rb +0 -65
- data/spec/lib/deterministic/option_spec.rb +0 -140
- data/spec/lib/deterministic/result/failure_spec.rb +0 -65
- data/spec/lib/deterministic/result/result_map_spec.rb +0 -155
- data/spec/lib/deterministic/result/result_shared.rb +0 -25
- data/spec/lib/deterministic/result/success_spec.rb +0 -41
- data/spec/lib/deterministic/result_spec.rb +0 -63
- data/spec/lib/deterministic/sequencer_spec.rb +0 -506
- data/spec/lib/edge_cases_spec.rb +0 -156
- data/spec/lib/enum_spec.rb +0 -114
- data/spec/lib/native_pattern_matching_spec.rb +0 -74
- data/spec/localization_adapter_spec.rb +0 -66
- data/spec/organizer/with_reducer_spec.rb +0 -56
- data/spec/organizer_key_aliases_spec.rb +0 -29
- data/spec/organizer_spec.rb +0 -115
- data/spec/readme_spec.rb +0 -45
- data/spec/sample/calculates_order_tax_action_spec.rb +0 -16
- data/spec/sample/calculates_tax_spec.rb +0 -30
- data/spec/sample/looks_up_tax_percentage_action_spec.rb +0 -55
- data/spec/sample/provides_free_shipping_action_spec.rb +0 -25
- data/spec/sample/tax/calculates_order_tax_action.rb +0 -10
- data/spec/sample/tax/calculates_tax.rb +0 -11
- data/spec/sample/tax/looks_up_tax_percentage_action.rb +0 -28
- data/spec/sample/tax/provides_free_shipping_action.rb +0 -11
- data/spec/spec_helper.rb +0 -32
- data/spec/support.rb +0 -1
- data/spec/test_doubles.rb +0 -656
- data/spec/testing/context_factory/iterate_spec.rb +0 -39
- data/spec/testing/context_factory/reduce_if_spec.rb +0 -40
- data/spec/testing/context_factory/reduce_until_spec.rb +0 -40
- data/spec/testing/context_factory/with_callback_spec.rb +0 -38
- 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,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
|