functional-light-service 0.2.4
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 +7 -0
- data/.gitignore +22 -0
- data/.rspec +3 -0
- data/.rubocop.yml +72 -0
- data/.travis.yml +22 -0
- data/Appraisals +3 -0
- data/CHANGELOG.md +37 -0
- data/CODE_OF_CONDUCT.md +22 -0
- data/Gemfile +6 -0
- data/LICENSE +22 -0
- data/README.md +1424 -0
- data/Rakefile +12 -0
- data/VERSION +1 -0
- data/functional-light-service.gemspec +26 -0
- data/gemfiles/activesupport_5.gemfile +8 -0
- data/gemfiles/activesupport_5.gemfile.lock +82 -0
- data/lib/functional-light-service/action.rb +102 -0
- data/lib/functional-light-service/configuration.rb +24 -0
- data/lib/functional-light-service/context/key_verifier.rb +118 -0
- data/lib/functional-light-service/context.rb +165 -0
- data/lib/functional-light-service/errors.rb +6 -0
- data/lib/functional-light-service/functional/enum.rb +254 -0
- data/lib/functional-light-service/functional/maybe.rb +14 -0
- data/lib/functional-light-service/functional/monad.rb +66 -0
- data/lib/functional-light-service/functional/null.rb +74 -0
- data/lib/functional-light-service/functional/option.rb +99 -0
- data/lib/functional-light-service/functional/result.rb +122 -0
- data/lib/functional-light-service/localization_adapter.rb +44 -0
- data/lib/functional-light-service/organizer/execute.rb +14 -0
- data/lib/functional-light-service/organizer/iterate.rb +22 -0
- data/lib/functional-light-service/organizer/reduce_if.rb +17 -0
- data/lib/functional-light-service/organizer/reduce_until.rb +20 -0
- data/lib/functional-light-service/organizer/scoped_reducable.rb +13 -0
- data/lib/functional-light-service/organizer/verify_call_method_exists.rb +28 -0
- data/lib/functional-light-service/organizer/with_callback.rb +26 -0
- data/lib/functional-light-service/organizer/with_reducer.rb +71 -0
- data/lib/functional-light-service/organizer/with_reducer_factory.rb +18 -0
- data/lib/functional-light-service/organizer/with_reducer_log_decorator.rb +105 -0
- data/lib/functional-light-service/organizer.rb +105 -0
- data/lib/functional-light-service/testing/context_factory.rb +40 -0
- data/lib/functional-light-service/testing.rb +1 -0
- data/lib/functional-light-service/version.rb +3 -0
- data/lib/functional-light-service.rb +29 -0
- 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 +11 -0
- data/spec/acceptance/after_actions_spec.rb +71 -0
- data/spec/acceptance/around_each_spec.rb +19 -0
- data/spec/acceptance/before_actions_spec.rb +98 -0
- data/spec/acceptance/custom_log_from_organizer_spec.rb +60 -0
- data/spec/acceptance/fail_spec.rb +24 -0
- data/spec/acceptance/include_warning_spec.rb +29 -0
- data/spec/acceptance/log_from_organizer_spec.rb +154 -0
- data/spec/acceptance/message_localization_spec.rb +118 -0
- data/spec/acceptance/not_having_call_method_warning_spec.rb +39 -0
- data/spec/acceptance/organizer/around_each_with_reduce_if_spec.rb +42 -0
- data/spec/acceptance/organizer/context_failure_and_skipping_spec.rb +65 -0
- data/spec/acceptance/organizer/execute_spec.rb +46 -0
- data/spec/acceptance/organizer/iterate_spec.rb +37 -0
- data/spec/acceptance/organizer/reduce_if_spec.rb +51 -0
- data/spec/acceptance/organizer/reduce_until_spec.rb +43 -0
- data/spec/acceptance/organizer/with_callback_spec.rb +110 -0
- data/spec/acceptance/rollback_spec.rb +132 -0
- data/spec/acceptance/skip_all_warning_spec.rb +20 -0
- data/spec/acceptance/testing/context_factory_spec.rb +54 -0
- data/spec/action_expected_keys_spec.rb +63 -0
- data/spec/action_expects_and_promises_spec.rb +93 -0
- data/spec/action_promised_keys_spec.rb +122 -0
- data/spec/action_spec.rb +89 -0
- data/spec/context/inspect_spec.rb +57 -0
- data/spec/context_spec.rb +197 -0
- data/spec/examples/amount_spec.rb +77 -0
- data/spec/examples/controller_spec.rb +63 -0
- data/spec/examples/validate_address_spec.rb +37 -0
- data/spec/lib/deterministic/class_mixin_spec.rb +24 -0
- data/spec/lib/deterministic/currify_spec.rb +88 -0
- data/spec/lib/deterministic/monad_axioms.rb +44 -0
- data/spec/lib/deterministic/monad_spec.rb +45 -0
- data/spec/lib/deterministic/null_spec.rb +58 -0
- data/spec/lib/deterministic/option_spec.rb +133 -0
- data/spec/lib/deterministic/result/failure_spec.rb +65 -0
- data/spec/lib/deterministic/result/result_map_spec.rb +154 -0
- data/spec/lib/deterministic/result/result_shared.rb +24 -0
- data/spec/lib/deterministic/result/success_spec.rb +41 -0
- data/spec/lib/deterministic/result_spec.rb +63 -0
- data/spec/lib/enum_spec.rb +112 -0
- data/spec/localization_adapter_spec.rb +83 -0
- data/spec/organizer/with_reducer_spec.rb +56 -0
- data/spec/organizer_key_aliases_spec.rb +29 -0
- data/spec/organizer_spec.rb +93 -0
- data/spec/readme_spec.rb +47 -0
- data/spec/sample/calculates_order_tax_action_spec.rb +16 -0
- data/spec/sample/calculates_tax_spec.rb +30 -0
- data/spec/sample/looks_up_tax_percentage_action_spec.rb +53 -0
- data/spec/sample/provides_free_shipping_action_spec.rb +25 -0
- data/spec/sample/tax/calculates_order_tax_action.rb +9 -0
- data/spec/sample/tax/calculates_tax.rb +11 -0
- data/spec/sample/tax/looks_up_tax_percentage_action.rb +27 -0
- data/spec/sample/tax/provides_free_shipping_action.rb +10 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/support.rb +1 -0
- data/spec/test_doubles.rb +552 -0
- data/spec/testing/context_factory/iterate_spec.rb +39 -0
- data/spec/testing/context_factory/reduce_if_spec.rb +40 -0
- data/spec/testing/context_factory/reduce_until_spec.rb +40 -0
- data/spec/testing/context_factory/with_callback_spec.rb +38 -0
- data/spec/testing/context_factory_spec.rb +55 -0
- metadata +285 -0
data/Rakefile
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
|
2
|
+
|
|
3
|
+
require "rubygems"
|
|
4
|
+
require "bundler/setup"
|
|
5
|
+
|
|
6
|
+
require 'rspec/core/rake_task'
|
|
7
|
+
require 'rubocop/rake_task'
|
|
8
|
+
RuboCop::RakeTask.new
|
|
9
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
10
|
+
|
|
11
|
+
task(:default).clear
|
|
12
|
+
task :default => %i[spec rubocop]
|
data/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.2.4
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
require File.expand_path('../lib/functional-light-service/version', __FILE__)
|
|
3
|
+
|
|
4
|
+
Gem::Specification.new do |gem|
|
|
5
|
+
gem.authors = ["Boscolo Michele"]
|
|
6
|
+
gem.email = ["miboscol@gmail.com"]
|
|
7
|
+
gem.description = %q{A service skeleton with an emphasis on simplicity with a pinch a functional programming}
|
|
8
|
+
gem.summary = %q{A service skeleton with an emphasis on simplicity with a pinch a functional programming}
|
|
9
|
+
gem.homepage = "https://github.com/sphynx79/functional-light-service"
|
|
10
|
+
gem.license = "MIT"
|
|
11
|
+
|
|
12
|
+
gem.files = `git ls-files`.split($\)
|
|
13
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
|
14
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
|
15
|
+
gem.name = "functional-light-service"
|
|
16
|
+
gem.require_paths = ["lib"]
|
|
17
|
+
gem.version = FunctionalLightService::VERSION
|
|
18
|
+
|
|
19
|
+
# gem.add_dependency("activesupport", ">= 5.2.2")
|
|
20
|
+
|
|
21
|
+
gem.add_development_dependency("activesupport", "~> 5.2.0")
|
|
22
|
+
gem.add_development_dependency("rspec", "~> 3.0")
|
|
23
|
+
gem.add_development_dependency("simplecov", "~> 0.16.1")
|
|
24
|
+
gem.add_development_dependency("rubocop", "~> 0.63.1")
|
|
25
|
+
gem.add_development_dependency("pry", "~> 0.12.2")
|
|
26
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: ../
|
|
3
|
+
specs:
|
|
4
|
+
light-service (0.6.1)
|
|
5
|
+
activesupport (>= 3.0)
|
|
6
|
+
|
|
7
|
+
GEM
|
|
8
|
+
remote: https://rubygems.org/
|
|
9
|
+
specs:
|
|
10
|
+
activesupport (5.0.0.1)
|
|
11
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
12
|
+
i18n (~> 0.7)
|
|
13
|
+
minitest (~> 5.1)
|
|
14
|
+
tzinfo (~> 1.1)
|
|
15
|
+
appraisal (2.1.0)
|
|
16
|
+
bundler
|
|
17
|
+
rake
|
|
18
|
+
thor (>= 0.14.0)
|
|
19
|
+
ast (2.3.0)
|
|
20
|
+
coderay (1.1.1)
|
|
21
|
+
concurrent-ruby (1.0.2)
|
|
22
|
+
diff-lcs (1.2.5)
|
|
23
|
+
docile (1.1.5)
|
|
24
|
+
i18n (0.7.0)
|
|
25
|
+
json (2.0.2)
|
|
26
|
+
method_source (0.8.2)
|
|
27
|
+
minitest (5.9.0)
|
|
28
|
+
parser (2.3.1.2)
|
|
29
|
+
ast (~> 2.2)
|
|
30
|
+
powerpack (0.1.1)
|
|
31
|
+
pry (0.10.4)
|
|
32
|
+
coderay (~> 1.1.0)
|
|
33
|
+
method_source (~> 0.8.1)
|
|
34
|
+
slop (~> 3.4)
|
|
35
|
+
rainbow (2.1.0)
|
|
36
|
+
rake (11.2.2)
|
|
37
|
+
rspec (3.5.0)
|
|
38
|
+
rspec-core (~> 3.5.0)
|
|
39
|
+
rspec-expectations (~> 3.5.0)
|
|
40
|
+
rspec-mocks (~> 3.5.0)
|
|
41
|
+
rspec-core (3.5.2)
|
|
42
|
+
rspec-support (~> 3.5.0)
|
|
43
|
+
rspec-expectations (3.5.0)
|
|
44
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
45
|
+
rspec-support (~> 3.5.0)
|
|
46
|
+
rspec-mocks (3.5.0)
|
|
47
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
48
|
+
rspec-support (~> 3.5.0)
|
|
49
|
+
rspec-support (3.5.0)
|
|
50
|
+
rubocop (0.42.0)
|
|
51
|
+
parser (>= 2.3.1.1, < 3.0)
|
|
52
|
+
powerpack (~> 0.1)
|
|
53
|
+
rainbow (>= 1.99.1, < 3.0)
|
|
54
|
+
ruby-progressbar (~> 1.7)
|
|
55
|
+
unicode-display_width (~> 1.0, >= 1.0.1)
|
|
56
|
+
ruby-progressbar (1.8.1)
|
|
57
|
+
simplecov (0.12.0)
|
|
58
|
+
docile (~> 1.1.0)
|
|
59
|
+
json (>= 1.8, < 3)
|
|
60
|
+
simplecov-html (~> 0.10.0)
|
|
61
|
+
simplecov-html (0.10.0)
|
|
62
|
+
slop (3.6.0)
|
|
63
|
+
thor (0.19.1)
|
|
64
|
+
thread_safe (0.3.5)
|
|
65
|
+
tzinfo (1.2.2)
|
|
66
|
+
thread_safe (~> 0.1)
|
|
67
|
+
unicode-display_width (1.1.1)
|
|
68
|
+
|
|
69
|
+
PLATFORMS
|
|
70
|
+
ruby
|
|
71
|
+
|
|
72
|
+
DEPENDENCIES
|
|
73
|
+
activesupport (~> 5.0)
|
|
74
|
+
appraisal (~> 2.0)
|
|
75
|
+
light-service!
|
|
76
|
+
pry (~> 0.10)
|
|
77
|
+
rspec (~> 3.0)
|
|
78
|
+
rubocop (~> 0.36)
|
|
79
|
+
simplecov (~> 0.11)
|
|
80
|
+
|
|
81
|
+
BUNDLED WITH
|
|
82
|
+
1.12.5
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
require 'active_support/deprecation'
|
|
2
|
+
|
|
3
|
+
module FunctionalLightService
|
|
4
|
+
module Action
|
|
5
|
+
def self.extended(base_class)
|
|
6
|
+
base_class.extend Macros
|
|
7
|
+
base_class.extend FunctionalLightService::Prelude::Result
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.included(base_class)
|
|
11
|
+
msg = "including FunctionalLightService::Action is deprecated. " \
|
|
12
|
+
"Please use `extend FunctionalLightService::Action` instead"
|
|
13
|
+
ActiveSupport::Deprecation.warn(msg)
|
|
14
|
+
base_class.extend Macros
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
module Macros
|
|
18
|
+
def expects(*args)
|
|
19
|
+
expected_keys.concat(args)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def promises(*args)
|
|
23
|
+
promised_keys.concat(args)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def expected_keys
|
|
27
|
+
@expected_keys ||= []
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def promised_keys
|
|
31
|
+
@promised_keys ||= []
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def ctx(*args)
|
|
35
|
+
@ctx ||= args
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def executed
|
|
39
|
+
define_singleton_method :execute do |context = {}|
|
|
40
|
+
action_context = create_action_context(context)
|
|
41
|
+
return action_context if action_context.stop_processing?
|
|
42
|
+
|
|
43
|
+
@ctx = action_context
|
|
44
|
+
|
|
45
|
+
# Store the action within the context
|
|
46
|
+
action_context.current_action = self
|
|
47
|
+
|
|
48
|
+
Context::KeyVerifier.verify_keys(action_context, self) do
|
|
49
|
+
action_context.define_accessor_methods_for_keys(all_keys)
|
|
50
|
+
|
|
51
|
+
catch(:jump_when_failed) do
|
|
52
|
+
call_before_action(action_context)
|
|
53
|
+
yield(action_context)
|
|
54
|
+
call_after_action(action_context)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def rolled_back
|
|
61
|
+
msg = "`rolled_back` macro can not be invoked again"
|
|
62
|
+
raise msg if respond_to?(:rollback)
|
|
63
|
+
|
|
64
|
+
define_singleton_method :rollback do |context = {}|
|
|
65
|
+
yield(context)
|
|
66
|
+
|
|
67
|
+
context
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
def create_action_context(context)
|
|
74
|
+
return context if context.is_a? FunctionalLightService::Context
|
|
75
|
+
|
|
76
|
+
FunctionalLightService::Context.make(context)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def all_keys
|
|
80
|
+
expected_keys + promised_keys
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def call_before_action(context)
|
|
84
|
+
invoke_callbacks(context[:_before_actions], context)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def call_after_action(context)
|
|
88
|
+
invoke_callbacks(context[:_after_actions], context)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def invoke_callbacks(callbacks, context)
|
|
92
|
+
return context unless callbacks
|
|
93
|
+
|
|
94
|
+
callbacks.each do |cb|
|
|
95
|
+
cb.call(context)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
context
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module FunctionalLightService
|
|
2
|
+
class Configuration
|
|
3
|
+
class << self
|
|
4
|
+
attr_writer :logger, :localization_adapter
|
|
5
|
+
|
|
6
|
+
def logger
|
|
7
|
+
@logger = _default_logger unless instance_variable_defined?("@logger")
|
|
8
|
+
@logger
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def localization_adapter
|
|
12
|
+
@localization_adapter ||= LocalizationAdapter.new
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def _default_logger
|
|
18
|
+
logger = Logger.new("/dev/null")
|
|
19
|
+
logger.level = Logger::WARN
|
|
20
|
+
logger
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
module FunctionalLightService
|
|
2
|
+
class Context
|
|
3
|
+
class KeyVerifier
|
|
4
|
+
attr_reader :context, :action
|
|
5
|
+
|
|
6
|
+
def initialize(context, action)
|
|
7
|
+
@context = context
|
|
8
|
+
@action = action
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def are_all_keys_in_context?(keys)
|
|
12
|
+
not_found_keys = keys_not_found(keys)
|
|
13
|
+
not_found_keys.none?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def keys_not_found(keys)
|
|
17
|
+
keys ||= context.keys
|
|
18
|
+
keys - context.keys
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def format_keys(keys)
|
|
22
|
+
keys.map { |k| ":#{k}" }.join(', ')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def error_message
|
|
26
|
+
"#{type_name} #{format_keys(keys_not_found(keys))} " \
|
|
27
|
+
"to be in the context during #{action}"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def throw_error_predicate(_keys)
|
|
31
|
+
raise NotImplementedError, 'Sorry, you have to override length'
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def verify
|
|
35
|
+
return context if context.failure?
|
|
36
|
+
|
|
37
|
+
if throw_error_predicate(keys)
|
|
38
|
+
Configuration.logger.error error_message
|
|
39
|
+
raise error_to_throw, error_message
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def self.verify_keys(context, action, &block)
|
|
46
|
+
ReservedKeysVerifier.new(context, action).verify
|
|
47
|
+
ExpectedKeyVerifier.new(context, action).verify
|
|
48
|
+
|
|
49
|
+
block.call
|
|
50
|
+
|
|
51
|
+
PromisedKeyVerifier.new(context, action).verify
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class ExpectedKeyVerifier < KeyVerifier
|
|
56
|
+
def type_name
|
|
57
|
+
"expected"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def keys
|
|
61
|
+
action.expected_keys
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def error_to_throw
|
|
65
|
+
ExpectedKeysNotInContextError
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def throw_error_predicate(keys)
|
|
69
|
+
!are_all_keys_in_context?(keys)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
class PromisedKeyVerifier < KeyVerifier
|
|
74
|
+
def type_name
|
|
75
|
+
"promised"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def keys
|
|
79
|
+
action.promised_keys
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def error_to_throw
|
|
83
|
+
PromisedKeysNotInContextError
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def throw_error_predicate(keys)
|
|
87
|
+
!are_all_keys_in_context?(keys)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
class ReservedKeysVerifier < KeyVerifier
|
|
92
|
+
def violated_keys
|
|
93
|
+
(action.promised_keys + action.expected_keys) & reserved_keys
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def error_message
|
|
97
|
+
"promised or expected keys cannot be a " \
|
|
98
|
+
"reserved key: [#{format_keys(violated_keys)}]"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def keys
|
|
102
|
+
violated_keys
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def error_to_throw
|
|
106
|
+
ReservedKeysInContextError
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def throw_error_predicate(keys)
|
|
110
|
+
keys.any?
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def reserved_keys
|
|
114
|
+
%i[message error_code current_action].freeze
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
require 'active_support/deprecation'
|
|
2
|
+
|
|
3
|
+
module FunctionalLightService
|
|
4
|
+
# rubocop:disable ClassLength
|
|
5
|
+
class Context < Hash
|
|
6
|
+
include FunctionalLightService::Prelude::Option
|
|
7
|
+
include FunctionalLightService::Prelude::Result
|
|
8
|
+
attr_accessor :outcome, :current_action
|
|
9
|
+
|
|
10
|
+
def initialize(context = {},
|
|
11
|
+
outcome = Success(:message => '', :error => nil))
|
|
12
|
+
@outcome = outcome
|
|
13
|
+
@skip_remaining = false
|
|
14
|
+
context.to_hash.each { |k, v| self[k] = v }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.make(context = {})
|
|
18
|
+
unless context.is_a?(Hash) || context.is_a?(FunctionalLightService::Context)
|
|
19
|
+
msg = 'Argument must be Hash or FunctionalLightService::Context'
|
|
20
|
+
raise ArgumentError, msg
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
context = new(context) unless context.is_a?(Context)
|
|
24
|
+
|
|
25
|
+
context.assign_aliases(context.delete(:_aliases)) if context[:_aliases]
|
|
26
|
+
context
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def add_to_context(values)
|
|
30
|
+
merge! values
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def success?
|
|
34
|
+
@outcome.success?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def failure?
|
|
38
|
+
success? == false
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def skip_remaining?
|
|
42
|
+
@skip_remaining
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def reset_skip_remaining!
|
|
46
|
+
@outcome = Success(nil)
|
|
47
|
+
@skip_remaining = false
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def message
|
|
51
|
+
@outcome.value.dig(:message)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def error_code
|
|
55
|
+
@outcome.value.dig(:error)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def succeed!(message = nil, options = {})
|
|
59
|
+
message = Configuration.localization_adapter.success(message,
|
|
60
|
+
current_action,
|
|
61
|
+
options)
|
|
62
|
+
@outcome = Success(:message => message)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def fail!(message = nil, options_or_error_code = {})
|
|
66
|
+
options_or_error_code ||= {}
|
|
67
|
+
|
|
68
|
+
if options_or_error_code.is_a?(Hash)
|
|
69
|
+
error_code = options_or_error_code.delete(:error_code)
|
|
70
|
+
options = options_or_error_code
|
|
71
|
+
else
|
|
72
|
+
error_code = options_or_error_code
|
|
73
|
+
options = {}
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
message = Configuration.localization_adapter.failure(message,
|
|
77
|
+
current_action,
|
|
78
|
+
options)
|
|
79
|
+
|
|
80
|
+
@outcome = Failure(:message => message, :error => error_code)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def fail_and_return!(*args)
|
|
84
|
+
fail!(*args)
|
|
85
|
+
throw(:jump_when_failed, *args)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def fail_with_rollback!(message = nil, error_code = nil)
|
|
89
|
+
fail!(message, error_code)
|
|
90
|
+
raise FailWithRollbackError
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def skip_all!(message = nil)
|
|
94
|
+
warning_msg = "Using skip_all! has been deprecated, " \
|
|
95
|
+
"please use `skip_remaining!` instead."
|
|
96
|
+
ActiveSupport::Deprecation.warn(warning_msg)
|
|
97
|
+
|
|
98
|
+
skip_remaining!(message)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def skip_remaining!(message = nil)
|
|
102
|
+
@outcome = Success(:message => message)
|
|
103
|
+
@skip_remaining = true
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def stop_processing?
|
|
107
|
+
failure? || skip_remaining?
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def define_accessor_methods_for_keys(keys)
|
|
111
|
+
return if keys.nil?
|
|
112
|
+
|
|
113
|
+
keys.each do |key|
|
|
114
|
+
next if respond_to?(key.to_sym)
|
|
115
|
+
|
|
116
|
+
define_singleton_method(key.to_s) { fetch(key) }
|
|
117
|
+
define_singleton_method("#{key}=") { |value| self[key] = value }
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def assign_aliases(aliases)
|
|
122
|
+
@aliases = aliases
|
|
123
|
+
|
|
124
|
+
aliases.each_pair do |key, key_alias|
|
|
125
|
+
self[key_alias] = self[key]
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def aliases
|
|
130
|
+
@aliases ||= {}
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def [](key)
|
|
134
|
+
key = aliases.key(key) || key
|
|
135
|
+
return super(key)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def fetch(key, default = nil, &blk)
|
|
139
|
+
self[key] ||= if block_given?
|
|
140
|
+
super(key, &blk)
|
|
141
|
+
else
|
|
142
|
+
super
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def inspect
|
|
147
|
+
"#{self.class}(#{self}, " \
|
|
148
|
+
+ "success: #{success?}, " \
|
|
149
|
+
+ "message: #{check_nil(message)}, " \
|
|
150
|
+
+ "error_code: #{check_nil(error_code)}, " \
|
|
151
|
+
+ "skip_remaining: #{@skip_remaining}, " \
|
|
152
|
+
+ "aliases: #{@aliases}" \
|
|
153
|
+
+ ")"
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
private
|
|
157
|
+
|
|
158
|
+
def check_nil(value)
|
|
159
|
+
return 'nil' unless value
|
|
160
|
+
|
|
161
|
+
"'#{value}'"
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
# rubocop:enable ClassLength
|
|
165
|
+
end
|