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,28 +0,0 @@
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
@@ -1,81 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FunctionalLightService
4
- module Organizer
5
- class WithReducer
6
- attr_reader :context
7
- attr_accessor :organizer
8
-
9
- def initialize(monitored_organizer = nil)
10
- @organizer = monitored_organizer
11
- end
12
-
13
- def with(data = {})
14
- @context = FunctionalLightService::Context.make(data)
15
- @context.organized_by = organizer
16
- self
17
- end
18
-
19
- # Handler di default condiviso: prima veniva creata una classe anonima
20
- # per ogni WithReducer senza around_each
21
- NOOP_AROUND_EACH_HANDLER = ->(_context, &block) { block.call }
22
-
23
- def around_each(handler)
24
- @around_each_handler = handler
25
- self
26
- end
27
-
28
- def around_each_handler
29
- @around_each_handler || NOOP_AROUND_EACH_HANDLER
30
- end
31
-
32
- def reduce(*actions)
33
- raise "No action(s) were provided" if actions.empty?
34
-
35
- actions.flatten!
36
-
37
- actions.each_with_index.with_object(context) do |(action, index), current_context|
38
- invoke_action(current_context, action)
39
- rescue FailWithRollbackError
40
- reduce_rollback(actions, index)
41
- ensure
42
- # For logging
43
- yield(current_context, action) if block_given?
44
- end
45
- end
46
-
47
- def reduce_rollback(actions, index_of_failed_action = nil)
48
- reversable_actions(actions, index_of_failed_action)
49
- .reverse
50
- .reduce(context) do |context, action|
51
- if action.respond_to?(:rollback)
52
- action.rollback(context)
53
- else
54
- context
55
- end
56
- end
57
- end
58
-
59
- private
60
-
61
- def invoke_action(current_context, action)
62
- around_each_handler.call(current_context) do
63
- if action.respond_to?(:call)
64
- action.call(current_context)
65
- else
66
- action.execute(current_context)
67
- end
68
- end
69
- end
70
-
71
- def reversable_actions(actions, index_of_failed_action = nil)
72
- # L'indice viene tracciato nel reduce: actions.index troverebbe la prima
73
- # occorrenza e con azioni duplicate il rollback sarebbe parziale
74
- index_of_failed_action ||= actions.index(@context.current_action) || 0
75
-
76
- # Reverse from the point where the fail was triggered
77
- actions.take(index_of_failed_action + 1)
78
- end
79
- end
80
- end
81
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FunctionalLightService
4
- module Organizer
5
- class WithReducerFactory
6
- def self.make(monitored_organizer)
7
- logger = monitored_organizer.logger || FunctionalLightService::Configuration.logger
8
- decorated = WithReducer.new(monitored_organizer)
9
-
10
- return decorated if logger.nil?
11
-
12
- WithReducerLogDecorator.new(
13
- monitored_organizer,
14
- :decorated => decorated,
15
- :logger => logger
16
- )
17
- end
18
- end
19
- end
20
- end
@@ -1,111 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FunctionalLightService
4
- module Organizer
5
- class WithReducerLogDecorator
6
- attr_reader :logged, :logger, :decorated, :organizer
7
-
8
- alias logged? logged
9
-
10
- def initialize(organizer, logger:, decorated: WithReducer.new)
11
- @decorated = decorated
12
- @organizer = organizer
13
-
14
- decorated.organizer = organizer
15
-
16
- @logger = logger
17
- @logged = false
18
- end
19
-
20
- def with(data = {})
21
- logger.info { "[FunctionalLightService] - calling organizer <#{organizer}>" }
22
-
23
- decorated.with(data)
24
-
25
- logger.info do
26
- "[FunctionalLightService] - keys in context: " \
27
- "#{extract_keys(decorated.context.keys)}"
28
- end
29
- self
30
- end
31
-
32
- def around_each(handler)
33
- decorated.around_each(handler)
34
- self
35
- end
36
-
37
- def reduce(*actions)
38
- decorated.reduce(*actions) do |context, action|
39
- next context if logged?
40
-
41
- if has_failure?(context)
42
- write_failure_log(context, action)
43
- next context
44
- end
45
-
46
- if skip_remaining?(context)
47
- write_skip_remaining_log(context, action)
48
- next context
49
- end
50
-
51
- write_log(action, context)
52
- end
53
- end
54
-
55
- private
56
-
57
- def write_log(action, context)
58
- return unless logger.info?
59
-
60
- logger.info("[FunctionalLightService] - executing <#{action}>")
61
- log_expects(action)
62
- log_promises(action)
63
- logger.info("[FunctionalLightService] - keys in context: "\
64
- "#{extract_keys(context.keys)}")
65
- end
66
-
67
- def log_expects(action)
68
- return unless defined?(action.expects) && action.expects.any?
69
-
70
- logger.info("[FunctionalLightService] - expects: " \
71
- "#{extract_keys(action.expects)}")
72
- end
73
-
74
- def log_promises(action)
75
- return unless defined?(action.promises) && action.promises.any?
76
-
77
- logger.info("[FunctionalLightService] - promises: " \
78
- "#{extract_keys(action.promises)}")
79
- end
80
-
81
- def extract_keys(keys)
82
- keys.map { |key| ":#{key}" }.join(', ')
83
- end
84
-
85
- def has_failure?(context)
86
- context.respond_to?(:failure?) && context.failure?
87
- end
88
-
89
- def write_failure_log(context, action)
90
- logger.warn("[FunctionalLightService] - :-((( <#{action}> has failed...")
91
- logger.warn("[FunctionalLightService] - context message: #{context.message}")
92
- @logged = true
93
- end
94
-
95
- def skip_remaining?(context)
96
- (context.respond_to?(:skip_remaining?) && context.skip_remaining?) ||
97
- (context.respond_to?(:skip_all_remaining?) && context.skip_all_remaining?)
98
- end
99
-
100
- def write_skip_remaining_log(context, action)
101
- return unless logger.info?
102
-
103
- msg = "[FunctionalLightService] - ;-) <#{action}> has decided " \
104
- "to skip the rest of the actions"
105
- logger.info(msg)
106
- logger.info("[FunctionalLightService] - context message: #{context.message}")
107
- @logged = true
108
- end
109
- end
110
- end
111
- end
@@ -1,129 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FunctionalLightService
4
- module Organizer
5
- def self.extended(base_class)
6
- base_class.extend ClassMethods
7
- base_class.extend Macros
8
- end
9
-
10
- def self.included(base_class)
11
- FunctionalLightService::Deprecations.warn(
12
- "Including FunctionalLightService::Organizer is deprecated; " \
13
- "use `extend FunctionalLightService::Organizer` instead"
14
- )
15
- extended(base_class)
16
- end
17
-
18
- # In case this module is included
19
- module ClassMethods
20
- def with(data = {})
21
- data[:_aliases] = @aliases if @aliases
22
-
23
- # Gli hook di classe vengono solo letti (mai azzerati): devono valere
24
- # per ogni chiamata, anche concorrente
25
- data[:_before_actions] = @before_actions.dup if @before_actions
26
- data[:_after_actions] = @after_actions.dup if @after_actions
27
-
28
- WithReducerFactory.make(self).with(data)
29
- end
30
-
31
- def reduce(*actions)
32
- with({}).reduce(actions)
33
- end
34
-
35
- def reduce_if(condition_block, steps)
36
- ReduceIf.run(self, condition_block, steps)
37
- end
38
-
39
- def reduce_if_else(condition_block, if_steps, else_steps)
40
- ReduceIfElse.run(self, condition_block, if_steps, else_steps)
41
- end
42
-
43
- def reduce_until(condition_block, steps)
44
- ReduceUntil.run(self, condition_block, steps)
45
- end
46
-
47
- def reduce_case(**args)
48
- ReduceCase.run(self, **args)
49
- end
50
-
51
- def reduce_while(condition_block, steps)
52
- ReduceWhile.run(self, condition_block, steps)
53
- end
54
-
55
- def iterate(collection_key, steps)
56
- Iterate.run(self, collection_key, steps)
57
- end
58
-
59
- def execute(code_block = nil, &block)
60
- Execute.run(code_block || block)
61
- end
62
-
63
- def with_callback(action, steps)
64
- WithCallback.run(self, action, steps)
65
- end
66
-
67
- def log_with(logger)
68
- @logger = logger
69
- end
70
-
71
- def logger
72
- @logger
73
- end
74
-
75
- def add_to_context(**args)
76
- args.map do |key, value|
77
- execute(->(ctx) do
78
- ctx[key.to_sym] = value
79
- ctx.define_accessor_methods_for_keys([key])
80
- end)
81
- end
82
- end
83
-
84
- def add_aliases(args)
85
- execute(->(ctx) { ctx.assign_aliases(ctx.aliases.merge(args)) })
86
- end
87
- end
88
-
89
- module Macros
90
- def aliases(key_hash)
91
- @aliases = key_hash
92
- end
93
-
94
- # This looks like an accessor,
95
- # but it's used as a macro in the Organizer
96
- def before_actions(*logic)
97
- self.before_actions = logic
98
- end
99
-
100
- def before_actions=(logic)
101
- @before_actions = logic.nil? ? nil : [logic].flatten
102
- end
103
-
104
- def append_before_actions(action)
105
- @before_actions ||= []
106
- @before_actions.push(action)
107
- end
108
-
109
- def remove_before_actions(action)
110
- @before_actions&.delete(action)
111
- end
112
-
113
- # This looks like an accessor,
114
- # but it's used as a macro in the Organizer
115
- def after_actions(*logic)
116
- self.after_actions = logic
117
- end
118
-
119
- def after_actions=(logic)
120
- @after_actions = logic.nil? ? nil : [logic].flatten
121
- end
122
-
123
- def append_after_actions(action)
124
- @after_actions ||= []
125
- @after_actions.push(action)
126
- end
127
- end
128
- end
129
- end
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FunctionalLightService
4
- module Testing
5
- class ContextFactory
6
- attr_reader :organizer
7
-
8
- def self.make_from(organizer)
9
- new(organizer)
10
- end
11
-
12
- def for(action)
13
- @target_action = action
14
- self
15
- end
16
-
17
- # More than one arguments can be passed to the
18
- # Organizer's #call method
19
- def with(...)
20
- hook = nil
21
- hook = ->(ctx) do
22
- if ctx.current_action == @target_action
23
- # L'hook non deve essere re-invocato quando il context
24
- # verra' usato con Action#execute nel test
25
- ctx[:_before_actions].delete(hook)
26
-
27
- throw(:return_ctx_from_execution, ctx)
28
- end
29
- end
30
-
31
- @organizer.append_before_actions(hook)
32
-
33
- begin
34
- catch(:return_ctx_from_execution) do
35
- @organizer.call(...)
36
- end
37
- ensure
38
- # L'hook e' per-chiamata: la classe organizer non deve conservarlo
39
- @organizer.remove_before_actions(hook)
40
- end
41
- end
42
-
43
- def initialize(organizer)
44
- @organizer = organizer
45
- end
46
- end
47
- end
48
- end
@@ -1,3 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'functional-light-service/testing/context_factory'
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module FunctionalLightService
4
- VERSION = "6.2.0"
5
- end
Binary file
Binary file
Binary file
Binary file
@@ -1,11 +0,0 @@
1
- require 'spec_helper'
2
- require 'test_doubles'
3
-
4
- RSpec.describe TestDoubles::AdditionOrganizer do
5
- it 'Adds 1, 2 and 3 to the initial value of 1' do
6
- result = TestDoubles::AdditionOrganizer.call(1)
7
- number = result.fetch(:number)
8
-
9
- expect(number).to eq(7)
10
- end
11
- end
@@ -1,87 +0,0 @@
1
- require 'spec_helper'
2
- require 'test_doubles'
3
-
4
- RSpec.describe 'Action after_actions' do
5
- # Gli hook restano sulla classe (non vengono piu consumati da #with):
6
- # i test double sono condivisi, quindi vanno ripuliti dopo ogni esempio
7
- after do
8
- TestDoubles::AdditionOrganizer.after_actions = nil
9
- TestDoubles::TestIterate.after_actions = nil
10
- end
11
-
12
- describe 'works with simple organizers - from outside' do
13
- it 'can be used to inject code block before each action' do
14
- TestDoubles::AdditionOrganizer.after_actions = ->(ctx) do
15
- ctx.number -= 2 if ctx.current_action == TestDoubles::AddsThreeAction
16
- end
17
-
18
- result = TestDoubles::AdditionOrganizer.call(0)
19
-
20
- expect(result.fetch(:number)).to eq(4)
21
- end
22
-
23
- it 'works with iterator' do
24
- TestDoubles::TestIterate.after_actions = [
25
- ->(ctx) { ctx.number -= 2 if ctx.current_action == TestDoubles::AddsOneAction }
26
- ]
27
-
28
- result = TestDoubles::TestIterate.call(:number => 0,
29
- :counters => [1, 2, 3, 4])
30
-
31
- expect(result).to be_success
32
- expect(result.number).to eq(-4)
33
- end
34
- end
35
-
36
- describe 'can be added to organizers declaratively' do
37
- module AfterActions
38
- class AdditionOrganizer
39
- extend FunctionalLightService::Organizer
40
-
41
- after_actions ->(ctx) do
42
- ctx.number -= 2 if ctx.current_action == TestDoubles::AddsOneAction
43
- end,
44
- ->(ctx) do
45
- ctx.number -= 3 if ctx.current_action == TestDoubles::AddsThreeAction
46
- end
47
-
48
- def self.call(number)
49
- with(:number => number).reduce(actions)
50
- end
51
-
52
- def self.actions
53
- [
54
- TestDoubles::AddsOneAction,
55
- TestDoubles::AddsTwoAction,
56
- TestDoubles::AddsThreeAction
57
- ]
58
- end
59
- end
60
- end
61
-
62
- it 'accepts after_actions hook lambdas from organizer' do
63
- result = AfterActions::AdditionOrganizer.call(0)
64
-
65
- expect(result.fetch(:number)).to eq(1)
66
- end
67
-
68
- it 'keeps the declarative hooks on every subsequent call' do
69
- first = AfterActions::AdditionOrganizer.call(0)
70
- second = AfterActions::AdditionOrganizer.call(0)
71
-
72
- expect(first.fetch(:number)).to eq(1)
73
- expect(second.fetch(:number)).to eq(1)
74
- end
75
- end
76
-
77
- describe 'after_actions can be appended' do
78
- it 'adds to the :_after_actions collection' do
79
- TestDoubles::AdditionOrganizer.append_after_actions(
80
- ->(ctx) { ctx.number -= 3 if ctx.current_action == TestDoubles::AddsThreeAction }
81
- )
82
-
83
- result = TestDoubles::AdditionOrganizer.call(0)
84
- expect(result.fetch(:number)).to eq(3)
85
- end
86
- end
87
- end
@@ -1,19 +0,0 @@
1
- require 'spec_helper'
2
- require 'test_doubles'
3
-
4
- describe 'Executing arbitrary code around each action' do
5
- it 'can be used to log data' do
6
- context = { :number => 0, :logger => TestDoubles::TestLogger.new }
7
-
8
- result = TestDoubles::AroundEachOrganizer.call(context)
9
-
10
- expect(result.fetch(:number)).to eq(2)
11
- expect(result[:logger].logs).to eq(
12
- [{
13
- :action => TestDoubles::AddsTwoActionWithFetch,
14
- :before => 0,
15
- :after => 2
16
- }]
17
- )
18
- end
19
- end
@@ -1,115 +0,0 @@
1
- require 'spec_helper'
2
- require 'test_doubles'
3
-
4
- RSpec.describe 'Action before_actions' do
5
- # Gli hook restano sulla classe (non vengono piu consumati da #with):
6
- # i test double sono condivisi, quindi vanno ripuliti dopo ogni esempio
7
- after do
8
- TestDoubles::AdditionOrganizer.before_actions = nil
9
- TestDoubles::TestIterate.before_actions = nil
10
- TestDoubles::TestWithCallback.before_actions = nil
11
- end
12
-
13
- describe 'works with simple organizers - from outside' do
14
- it 'can be used to inject code block before each action' do
15
- TestDoubles::AdditionOrganizer.before_actions = ->(ctx) do
16
- ctx.number -= 2 if ctx.current_action == TestDoubles::AddsThreeAction
17
- end
18
-
19
- result = TestDoubles::AdditionOrganizer.call(0)
20
-
21
- expect(result.fetch(:number)).to eq(4)
22
- end
23
-
24
- it 'works with iterator' do
25
- TestDoubles::TestIterate.before_actions = [
26
- ->(ctx) { ctx.number -= 2 if ctx.current_action == TestDoubles::AddsOneAction }
27
- ]
28
-
29
- result = TestDoubles::TestIterate.call(:number => 0,
30
- :counters => [1, 2, 3, 4])
31
-
32
- expect(result).to be_success
33
- expect(result.number).to eq(-4)
34
- end
35
- end
36
-
37
- describe 'can be added to organizers declaratively' do
38
- module BeforeActions
39
- class AdditionOrganizer
40
- extend FunctionalLightService::Organizer
41
-
42
- before_actions ->(ctx) do
43
- ctx.number -= 2 if ctx.current_action == TestDoubles::AddsOneAction
44
- end,
45
- ->(ctx) do
46
- ctx.number -= 3 if ctx.current_action == TestDoubles::AddsThreeAction
47
- end
48
-
49
- def self.call(number)
50
- with(:number => number).reduce(actions)
51
- end
52
-
53
- def self.actions
54
- [
55
- TestDoubles::AddsOneAction,
56
- TestDoubles::AddsTwoAction,
57
- TestDoubles::AddsThreeAction
58
- ]
59
- end
60
- end
61
- end
62
-
63
- it 'accepts before_actions hook lambdas from organizer' do
64
- result = BeforeActions::AdditionOrganizer.call(0)
65
-
66
- expect(result.fetch(:number)).to eq(1)
67
- end
68
-
69
- it 'keeps the declarative hooks on every subsequent call' do
70
- first = BeforeActions::AdditionOrganizer.call(0)
71
- second = BeforeActions::AdditionOrganizer.call(0)
72
-
73
- expect(first.fetch(:number)).to eq(1)
74
- expect(second.fetch(:number)).to eq(1)
75
- end
76
- end
77
-
78
- describe 'works with callbacks' do
79
- it 'can interact with actions from the outside' do
80
- TestDoubles::TestWithCallback.before_actions = [
81
- ->(ctx) { ctx.total -= 1000 if ctx.current_action == TestDoubles::AddToTotalAction }
82
- ]
83
- result = TestDoubles::TestWithCallback.call
84
-
85
- expect(result.counter).to eq(3)
86
- expect(result.total).to eq(-2994)
87
- end
88
- end
89
-
90
- describe 'can halt all execution with a raised error' do
91
- it 'does not call the rest of the callback steps' do
92
- class SkipContextError < StandardError
93
- attr_reader :ctx
94
-
95
- def initialize(msg, ctx)
96
- @ctx = ctx
97
- super(msg)
98
- end
99
- end
100
- TestDoubles::TestWithCallback.before_actions = [
101
- ->(ctx) do
102
- if ctx.current_action == TestDoubles::IncrementCountAction
103
- ctx.total -= 1000
104
- raise SkipContextError.new("stop context now", ctx)
105
- end
106
- end
107
- ]
108
- begin
109
- TestDoubles::TestWithCallback.call
110
- rescue SkipContextError => e
111
- expect(e.ctx).not_to be_empty
112
- end
113
- end
114
- end
115
- end