functional-light-service 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|