bcdd-result 0.6.0 → 0.7.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/.rubocop.yml +24 -11
- data/CHANGELOG.md +28 -0
- data/README.md +585 -160
- data/lib/bcdd/result/context/expectations/mixin.rb +35 -0
- data/lib/bcdd/result/context/expectations.rb +41 -0
- data/lib/bcdd/result/context/failure.rb +9 -0
- data/lib/bcdd/result/context/mixin.rb +38 -0
- data/lib/bcdd/result/context/success.rb +15 -0
- data/lib/bcdd/result/context.rb +74 -0
- data/lib/bcdd/result/{expectations/contract → contract}/disabled.rb +2 -2
- data/lib/bcdd/result/{expectations → contract}/error.rb +5 -3
- data/lib/bcdd/result/{expectations/contract → contract}/evaluator.rb +2 -2
- data/lib/bcdd/result/{expectations/contract → contract}/for_types.rb +2 -2
- data/lib/bcdd/result/{expectations/contract → contract}/for_types_and_values.rb +10 -8
- data/lib/bcdd/result/contract/interface.rb +21 -0
- data/lib/bcdd/result/{expectations → contract}/type_checker.rb +1 -1
- data/lib/bcdd/result/contract.rb +43 -0
- data/lib/bcdd/result/error.rb +7 -9
- data/lib/bcdd/result/expectations/mixin.rb +14 -9
- data/lib/bcdd/result/expectations.rb +28 -37
- data/lib/bcdd/result/failure/methods.rb +21 -0
- data/lib/bcdd/result/failure.rb +2 -16
- data/lib/bcdd/result/mixin.rb +8 -3
- data/lib/bcdd/result/success/methods.rb +21 -0
- data/lib/bcdd/result/success.rb +2 -16
- data/lib/bcdd/result/version.rb +1 -1
- data/lib/bcdd/result.rb +6 -4
- data/sig/bcdd/result.rbs +227 -83
- metadata +18 -10
- data/lib/bcdd/result/expectations/contract/interface.rb +0 -21
- data/lib/bcdd/result/expectations/contract.rb +0 -25
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result::Context
|
4
|
+
module Expectations::Mixin
|
5
|
+
METHODS = <<~RUBY
|
6
|
+
def Success(...)
|
7
|
+
_Result::Success(...)
|
8
|
+
end
|
9
|
+
|
10
|
+
def Failure(...)
|
11
|
+
_Result::Failure(...)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def _Result
|
17
|
+
@_Result ||= Result.with(subject: self)
|
18
|
+
end
|
19
|
+
RUBY
|
20
|
+
|
21
|
+
module Addons
|
22
|
+
module Continuable
|
23
|
+
private def Continue(**value)
|
24
|
+
Success.new(type: :continued, value: value, subject: self)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
OPTIONS = { Continue: Continuable }.freeze
|
29
|
+
|
30
|
+
def self.options(names)
|
31
|
+
Array(names).filter_map { |name| OPTIONS[name] }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result::Context
|
4
|
+
class Expectations
|
5
|
+
require_relative 'expectations/mixin'
|
6
|
+
|
7
|
+
def self.mixin(success: nil, failure: nil, with: nil)
|
8
|
+
addons = Mixin::Addons.options(with)
|
9
|
+
|
10
|
+
mod = ::BCDD::Result::Expectations::Mixin.module!
|
11
|
+
mod.const_set(:Result, new(success: success, failure: failure).freeze)
|
12
|
+
mod.module_eval(Mixin::METHODS)
|
13
|
+
mod.send(:include, *addons) unless addons.empty?
|
14
|
+
mod
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(subject: nil, success: nil, failure: nil, contract: nil)
|
18
|
+
@subject = subject
|
19
|
+
|
20
|
+
@contract = contract if contract.is_a?(::BCDD::Result::Contract::Evaluator)
|
21
|
+
|
22
|
+
@contract ||= ::BCDD::Result::Contract.new(success: success, failure: failure).freeze
|
23
|
+
end
|
24
|
+
|
25
|
+
def Success(type, **value)
|
26
|
+
Success.new(type: type, value: value, subject: subject, expectations: contract)
|
27
|
+
end
|
28
|
+
|
29
|
+
def Failure(type, **value)
|
30
|
+
Failure.new(type: type, value: value, subject: subject, expectations: contract)
|
31
|
+
end
|
32
|
+
|
33
|
+
def with(subject:)
|
34
|
+
self.class.new(subject: subject, contract: contract)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
attr_reader :subject, :contract
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result::Context
|
4
|
+
module Mixin
|
5
|
+
module Methods
|
6
|
+
def Success(type, **value)
|
7
|
+
Success.new(type: type, value: value, subject: self)
|
8
|
+
end
|
9
|
+
|
10
|
+
def Failure(type, **value)
|
11
|
+
Failure.new(type: type, value: value, subject: self)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module Addons
|
16
|
+
module Continuable
|
17
|
+
private def Continue(**value)
|
18
|
+
Success.new(type: :continued, value: value, subject: self)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
OPTIONS = { Continue: Continuable }.freeze
|
23
|
+
|
24
|
+
def self.options(names)
|
25
|
+
Array(names).filter_map { |name| OPTIONS[name] }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.mixin(with: nil)
|
31
|
+
addons = Mixin::Addons.options(with)
|
32
|
+
|
33
|
+
mod = ::BCDD::Result::Mixin.module!
|
34
|
+
mod.send(:include, Mixin::Methods)
|
35
|
+
mod.send(:include, *addons) unless addons.empty?
|
36
|
+
mod
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result::Context::Success < BCDD::Result::Context
|
4
|
+
include ::BCDD::Result::Success::Methods
|
5
|
+
|
6
|
+
def and_expose(type, keys)
|
7
|
+
unless keys.is_a?(::Array) && !keys.empty? && keys.all?(::Symbol)
|
8
|
+
raise ::ArgumentError, 'keys must be an Array of Symbols'
|
9
|
+
end
|
10
|
+
|
11
|
+
exposed_value = acc.merge(value).slice(*keys)
|
12
|
+
|
13
|
+
self.class.new(type: type, value: exposed_value, subject: subject)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result
|
4
|
+
class Context < self
|
5
|
+
require_relative 'context/failure'
|
6
|
+
require_relative 'context/success'
|
7
|
+
require_relative 'context/mixin'
|
8
|
+
require_relative 'context/expectations'
|
9
|
+
|
10
|
+
def self.Success(type, **value)
|
11
|
+
Success.new(type: type, value: value)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.Failure(type, **value)
|
15
|
+
Failure.new(type: type, value: value)
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(type:, value:, subject: nil, expectations: nil)
|
19
|
+
value.is_a?(::Hash) or raise ::ArgumentError, 'value must be a Hash'
|
20
|
+
|
21
|
+
@acc = {}
|
22
|
+
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
def and_then(method_name = nil, **context_data, &block)
|
27
|
+
super(method_name, context_data, &block)
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
attr_reader :acc
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
SubjectMethodArity = ->(method) do
|
37
|
+
return 0 if method.arity.zero?
|
38
|
+
return 1 if method.parameters.map(&:first).all?(/\Akey/)
|
39
|
+
|
40
|
+
-1
|
41
|
+
end
|
42
|
+
|
43
|
+
def call_subject_method(method_name, context)
|
44
|
+
method = subject.method(method_name)
|
45
|
+
|
46
|
+
acc.merge!(value.merge(context))
|
47
|
+
|
48
|
+
result =
|
49
|
+
case SubjectMethodArity[method]
|
50
|
+
when 0 then subject.send(method_name)
|
51
|
+
when 1 then subject.send(method_name, **acc)
|
52
|
+
else raise Error::InvalidSubjectMethodArity.build(subject: subject, method: method, max_arity: 1)
|
53
|
+
end
|
54
|
+
|
55
|
+
ensure_result_object(result, origin: :method)
|
56
|
+
end
|
57
|
+
|
58
|
+
def ensure_result_object(result, origin:)
|
59
|
+
raise_unexpected_outcome_error(result, origin) unless result.is_a?(Context)
|
60
|
+
|
61
|
+
return result.tap { _1.acc.merge!(acc) } if result.subject.equal?(subject)
|
62
|
+
|
63
|
+
raise Error::InvalidResultSubject.build(given_result: result, expected_subject: subject)
|
64
|
+
end
|
65
|
+
|
66
|
+
EXPECTED_OUTCOME = 'BCDD::Result::Context::Success or BCDD::Result::Context::Failure'
|
67
|
+
|
68
|
+
def raise_unexpected_outcome_error(result, origin)
|
69
|
+
raise Error::UnexpectedOutcome.build(outcome: result, origin: origin, expected: EXPECTED_OUTCOME)
|
70
|
+
end
|
71
|
+
|
72
|
+
private_constant :SubjectMethodArity, :EXPECTED_OUTCOME
|
73
|
+
end
|
74
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
class BCDD::Result::
|
3
|
+
class BCDD::Result::Contract::Error < BCDD::Result::Error
|
4
4
|
class UnexpectedType < self
|
5
5
|
def self.build(type:, allowed_types:)
|
6
6
|
new("type :#{type} is not allowed. Allowed types: #{allowed_types.map(&:inspect).join(', ')}")
|
@@ -8,8 +8,10 @@ class BCDD::Result::Expectations::Error < BCDD::Result::Error
|
|
8
8
|
end
|
9
9
|
|
10
10
|
class UnexpectedValue < self
|
11
|
-
def self.build(type:, value:)
|
12
|
-
|
11
|
+
def self.build(type:, value:, cause: nil)
|
12
|
+
cause_message = " (#{cause.message})" if cause
|
13
|
+
|
14
|
+
new("value #{value.inspect} is not allowed for :#{type} type#{cause_message}")
|
13
15
|
end
|
14
16
|
end
|
15
17
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
class BCDD::Result
|
3
|
+
class BCDD::Result
|
4
4
|
class Contract::Evaluator
|
5
5
|
include Contract::Interface
|
6
6
|
|
@@ -25,7 +25,7 @@ class BCDD::Result::Expectations
|
|
25
25
|
def type!(type)
|
26
26
|
return type if type?(type)
|
27
27
|
|
28
|
-
raise Error::UnexpectedType.build(type: type, allowed_types: allowed_types)
|
28
|
+
raise Contract::Error::UnexpectedType.build(type: type, allowed_types: allowed_types)
|
29
29
|
end
|
30
30
|
|
31
31
|
def type_and_value!(data)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
class BCDD::Result
|
3
|
+
class BCDD::Result
|
4
4
|
class Contract::ForTypes
|
5
5
|
include Contract::Interface
|
6
6
|
|
@@ -17,7 +17,7 @@ class BCDD::Result::Expectations
|
|
17
17
|
def type!(type)
|
18
18
|
return type if type?(type)
|
19
19
|
|
20
|
-
raise Error::UnexpectedType.build(type: type, allowed_types: allowed_types)
|
20
|
+
raise Contract::Error::UnexpectedType.build(type: type, allowed_types: allowed_types)
|
21
21
|
end
|
22
22
|
|
23
23
|
def type_and_value!(data)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
class BCDD::Result
|
3
|
+
class BCDD::Result
|
4
4
|
class Contract::ForTypesAndValues
|
5
5
|
include Contract::Interface
|
6
6
|
|
@@ -23,15 +23,17 @@ class BCDD::Result::Expectations
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def type_and_value!(data)
|
26
|
-
type = data.type
|
27
|
-
value = data.value
|
28
|
-
allowed_value = @types_and_values[type!(type)]
|
26
|
+
type, value = data.type, data.value
|
29
27
|
|
30
|
-
|
28
|
+
value_checking = @types_and_values[type!(type)]
|
31
29
|
|
32
|
-
|
33
|
-
|
34
|
-
|
30
|
+
checking_result = value_checking === value
|
31
|
+
|
32
|
+
return value if checking_result || (Contract.nil_as_valid_value_checking? && checking_result.nil?)
|
33
|
+
|
34
|
+
raise Contract::Error::UnexpectedValue.build(type: type, value: value)
|
35
|
+
rescue ::NoMatchingPatternError => e
|
36
|
+
raise Contract::Error::UnexpectedValue.build(type: data.type, value: data.value, cause: e)
|
35
37
|
end
|
36
38
|
end
|
37
39
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BCDD::Result
|
4
|
+
module Contract::Interface
|
5
|
+
def allowed_types
|
6
|
+
raise Error::NotImplemented
|
7
|
+
end
|
8
|
+
|
9
|
+
def type?(_type)
|
10
|
+
raise Error::NotImplemented
|
11
|
+
end
|
12
|
+
|
13
|
+
def type!(_type)
|
14
|
+
raise Error::NotImplemented
|
15
|
+
end
|
16
|
+
|
17
|
+
def type_and_value!(_data)
|
18
|
+
raise Error::NotImplemented
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BCDD::Result::Contract
|
4
|
+
require_relative 'contract/error'
|
5
|
+
require_relative 'contract/type_checker'
|
6
|
+
require_relative 'contract/interface'
|
7
|
+
require_relative 'contract/evaluator'
|
8
|
+
require_relative 'contract/disabled'
|
9
|
+
require_relative 'contract/for_types'
|
10
|
+
require_relative 'contract/for_types_and_values'
|
11
|
+
|
12
|
+
NONE = Evaluator.new(Disabled, Disabled).freeze
|
13
|
+
|
14
|
+
def self.evaluate(data, contract)
|
15
|
+
contract ||= NONE
|
16
|
+
|
17
|
+
contract.type_and_value!(data)
|
18
|
+
|
19
|
+
TypeChecker.new(data.type, expectations: contract)
|
20
|
+
end
|
21
|
+
|
22
|
+
ToEnsure = ->(spec) do
|
23
|
+
return Disabled if spec.nil?
|
24
|
+
|
25
|
+
spec.is_a?(::Hash) ? ForTypesAndValues.new(spec) : ForTypes.new(Array(spec))
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.new(success:, failure:)
|
29
|
+
Evaluator.new(ToEnsure[success], ToEnsure[failure])
|
30
|
+
end
|
31
|
+
|
32
|
+
@nil_as_valid_value_checking = false
|
33
|
+
|
34
|
+
def self.nil_as_valid_value_checking!(enabled: true)
|
35
|
+
@nil_as_valid_value_checking = enabled
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.nil_as_valid_value_checking?
|
39
|
+
@nil_as_valid_value_checking
|
40
|
+
end
|
41
|
+
|
42
|
+
private_constant :ToEnsure
|
43
|
+
end
|
data/lib/bcdd/result/error.rb
CHANGED
@@ -15,16 +15,14 @@ class BCDD::Result::Error < StandardError
|
|
15
15
|
end
|
16
16
|
|
17
17
|
class UnexpectedOutcome < self
|
18
|
-
def self.build(outcome:, origin:)
|
19
|
-
|
20
|
-
"Unexpected outcome: #{outcome.inspect}. The #{origin} must return this object wrapped by " \
|
21
|
-
'BCDD::Result::Success or BCDD::Result::Failure'
|
18
|
+
def self.build(outcome:, origin:, expected: nil)
|
19
|
+
expected ||= 'BCDD::Result::Success or BCDD::Result::Failure'
|
22
20
|
|
23
|
-
new(
|
21
|
+
new("Unexpected outcome: #{outcome.inspect}. The #{origin} must return this object wrapped by #{expected}")
|
24
22
|
end
|
25
23
|
end
|
26
24
|
|
27
|
-
class
|
25
|
+
class InvalidResultSubject < self
|
28
26
|
def self.build(given_result:, expected_subject:)
|
29
27
|
message =
|
30
28
|
"You cannot call #and_then and return a result that does not belong to the subject!\n" \
|
@@ -36,9 +34,9 @@ class BCDD::Result::Error < StandardError
|
|
36
34
|
end
|
37
35
|
end
|
38
36
|
|
39
|
-
class
|
40
|
-
def self.build(subject:, method:)
|
41
|
-
new("#{subject.class}##{method.name} has unsupported arity (#{method.arity}). Expected 0
|
37
|
+
class InvalidSubjectMethodArity < self
|
38
|
+
def self.build(subject:, method:, max_arity:)
|
39
|
+
new("#{subject.class}##{method.name} has unsupported arity (#{method.arity}). Expected 0..#{max_arity}")
|
42
40
|
end
|
43
41
|
end
|
44
42
|
|
@@ -1,27 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
class BCDD::Result
|
4
|
-
module Mixin
|
3
|
+
class BCDD::Result
|
4
|
+
module Expectations::Mixin
|
5
5
|
METHODS = <<~RUBY
|
6
6
|
def Success(...)
|
7
|
-
|
7
|
+
_Result.Success(...)
|
8
8
|
end
|
9
9
|
|
10
10
|
def Failure(...)
|
11
|
-
|
11
|
+
_Result.Failure(...)
|
12
12
|
end
|
13
13
|
|
14
14
|
private
|
15
15
|
|
16
|
-
def
|
17
|
-
@
|
16
|
+
def _Result
|
17
|
+
@_Result ||= Result.with(subject: self)
|
18
18
|
end
|
19
19
|
RUBY
|
20
20
|
|
21
21
|
module Addons
|
22
22
|
module Continuable
|
23
23
|
private def Continue(value)
|
24
|
-
|
24
|
+
Success.new(type: :continued, value: value, subject: self)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
@@ -31,7 +31,12 @@ class BCDD::Result::Expectations
|
|
31
31
|
Array(names).filter_map { |name| OPTIONS[name] }
|
32
32
|
end
|
33
33
|
end
|
34
|
-
end
|
35
34
|
|
36
|
-
|
35
|
+
def self.module!
|
36
|
+
::Module.new do
|
37
|
+
def self.included(base); base.const_set(:ResultExpectationsMixin, self); end
|
38
|
+
def self.extended(base); base.const_set(:ResultExpectationsMixin, self); end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
37
42
|
end
|
@@ -1,50 +1,41 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
class BCDD::Result
|
4
|
-
|
5
|
-
|
6
|
-
require_relative 'expectations/contract'
|
7
|
-
require_relative 'expectations/type_checker'
|
8
|
-
|
9
|
-
def self.mixin(success: nil, failure: nil, with: nil)
|
10
|
-
addons = Mixin::Addons.options(with)
|
11
|
-
|
12
|
-
mod = Module.new
|
13
|
-
mod.const_set(:Expected, new(success: success, failure: failure).freeze)
|
14
|
-
mod.module_eval(Mixin::METHODS)
|
15
|
-
mod.send(:include, *addons) unless addons.empty?
|
16
|
-
mod
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.evaluate(data, expectations)
|
20
|
-
expectations ||= Contract::NONE
|
3
|
+
class BCDD::Result
|
4
|
+
class Expectations
|
5
|
+
require_relative 'expectations/mixin'
|
21
6
|
|
22
|
-
|
7
|
+
def self.mixin(success: nil, failure: nil, with: nil)
|
8
|
+
addons = Mixin::Addons.options(with)
|
23
9
|
|
24
|
-
|
25
|
-
|
10
|
+
mod = Mixin.module!
|
11
|
+
mod.const_set(:Result, new(success: success, failure: failure).freeze)
|
12
|
+
mod.module_eval(Mixin::METHODS)
|
13
|
+
mod.send(:include, *addons) unless addons.empty?
|
14
|
+
mod
|
15
|
+
end
|
26
16
|
|
27
|
-
|
28
|
-
|
17
|
+
def initialize(subject: nil, success: nil, failure: nil, contract: nil)
|
18
|
+
@subject = subject
|
29
19
|
|
30
|
-
|
20
|
+
@contract = contract if contract.is_a?(Contract::Evaluator)
|
31
21
|
|
32
|
-
|
33
|
-
|
22
|
+
@contract ||= Contract.new(success: success, failure: failure).freeze
|
23
|
+
end
|
34
24
|
|
35
|
-
|
36
|
-
|
37
|
-
|
25
|
+
def Success(type, value = nil)
|
26
|
+
Success.new(type: type, value: value, subject: subject, expectations: contract)
|
27
|
+
end
|
38
28
|
|
39
|
-
|
40
|
-
|
41
|
-
|
29
|
+
def Failure(type, value = nil)
|
30
|
+
Failure.new(type: type, value: value, subject: subject, expectations: contract)
|
31
|
+
end
|
42
32
|
|
43
|
-
|
44
|
-
|
45
|
-
|
33
|
+
def with(subject:)
|
34
|
+
self.class.new(subject: subject, contract: contract)
|
35
|
+
end
|
46
36
|
|
47
|
-
|
37
|
+
private
|
48
38
|
|
49
|
-
|
39
|
+
attr_reader :subject, :contract
|
40
|
+
end
|
50
41
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BCDD::Result::Failure::Methods
|
4
|
+
def success?(_type = nil)
|
5
|
+
false
|
6
|
+
end
|
7
|
+
|
8
|
+
def failure?(type = nil)
|
9
|
+
type.nil? || type_checker.allow_failure?([type])
|
10
|
+
end
|
11
|
+
|
12
|
+
def value_or
|
13
|
+
yield(value)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def name
|
19
|
+
:failure
|
20
|
+
end
|
21
|
+
end
|
data/lib/bcdd/result/failure.rb
CHANGED
@@ -2,23 +2,9 @@
|
|
2
2
|
|
3
3
|
class BCDD::Result
|
4
4
|
class Failure < self
|
5
|
-
|
6
|
-
false
|
7
|
-
end
|
5
|
+
require_relative 'failure/methods'
|
8
6
|
|
9
|
-
|
10
|
-
type.nil? || type_checker.allow_failure?([type])
|
11
|
-
end
|
12
|
-
|
13
|
-
def value_or
|
14
|
-
yield
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def name
|
20
|
-
:failure
|
21
|
-
end
|
7
|
+
include Methods
|
22
8
|
end
|
23
9
|
|
24
10
|
def self.Failure(type, value = nil)
|
data/lib/bcdd/result/mixin.rb
CHANGED
@@ -25,16 +25,21 @@ class BCDD::Result
|
|
25
25
|
Array(names).filter_map { |name| OPTIONS[name] }
|
26
26
|
end
|
27
27
|
end
|
28
|
+
|
29
|
+
def self.module!
|
30
|
+
::Module.new do
|
31
|
+
def self.included(base); base.const_set(:ResultMixin, self); end
|
32
|
+
def self.extended(base); base.const_set(:ResultMixin, self); end
|
33
|
+
end
|
34
|
+
end
|
28
35
|
end
|
29
36
|
|
30
37
|
def self.mixin(with: nil)
|
31
38
|
addons = Mixin::Addons.options(with)
|
32
39
|
|
33
|
-
mod =
|
40
|
+
mod = Mixin.module!
|
34
41
|
mod.send(:include, Mixin::Methods)
|
35
42
|
mod.send(:include, *addons) unless addons.empty?
|
36
43
|
mod
|
37
44
|
end
|
38
|
-
|
39
|
-
private_constant :Mixin
|
40
45
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BCDD::Result::Success::Methods
|
4
|
+
def success?(type = nil)
|
5
|
+
type.nil? || type_checker.allow_success?([type])
|
6
|
+
end
|
7
|
+
|
8
|
+
def failure?(_type = nil)
|
9
|
+
false
|
10
|
+
end
|
11
|
+
|
12
|
+
def value_or
|
13
|
+
value
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def name
|
19
|
+
:success
|
20
|
+
end
|
21
|
+
end
|
data/lib/bcdd/result/success.rb
CHANGED
@@ -2,23 +2,9 @@
|
|
2
2
|
|
3
3
|
class BCDD::Result
|
4
4
|
class Success < self
|
5
|
-
|
6
|
-
type.nil? || type_checker.allow_success?([type])
|
7
|
-
end
|
5
|
+
require_relative 'success/methods'
|
8
6
|
|
9
|
-
|
10
|
-
false
|
11
|
-
end
|
12
|
-
|
13
|
-
def value_or
|
14
|
-
value
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def name
|
20
|
-
:success
|
21
|
-
end
|
7
|
+
include Methods
|
22
8
|
end
|
23
9
|
|
24
10
|
def self.Success(type, value = nil)
|