bcdd-result 0.6.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +31 -11
  3. data/CHANGELOG.md +148 -0
  4. data/README.md +849 -242
  5. data/Rakefile +9 -3
  6. data/Steepfile +1 -1
  7. data/lib/bcdd/result/config/constant_alias.rb +33 -0
  8. data/lib/bcdd/result/config/options.rb +26 -0
  9. data/lib/bcdd/result/config/switcher.rb +82 -0
  10. data/lib/bcdd/result/config.rb +71 -0
  11. data/lib/bcdd/result/context/expectations/mixin.rb +23 -0
  12. data/lib/bcdd/result/context/expectations.rb +25 -0
  13. data/lib/bcdd/result/context/failure.rb +9 -0
  14. data/lib/bcdd/result/context/mixin.rb +41 -0
  15. data/lib/bcdd/result/context/success.rb +15 -0
  16. data/lib/bcdd/result/context.rb +74 -0
  17. data/lib/bcdd/result/{expectations/contract → contract}/disabled.rb +2 -2
  18. data/lib/bcdd/result/{expectations → contract}/error.rb +5 -3
  19. data/lib/bcdd/result/{expectations/contract → contract}/evaluator.rb +2 -2
  20. data/lib/bcdd/result/{expectations/contract → contract}/for_types.rb +2 -2
  21. data/lib/bcdd/result/contract/for_types_and_values.rb +44 -0
  22. data/lib/bcdd/result/contract/interface.rb +21 -0
  23. data/lib/bcdd/result/{expectations → contract}/type_checker.rb +1 -1
  24. data/lib/bcdd/result/contract.rb +33 -0
  25. data/lib/bcdd/result/error.rb +7 -9
  26. data/lib/bcdd/result/expectations/mixin.rb +19 -12
  27. data/lib/bcdd/result/expectations.rb +51 -36
  28. data/lib/bcdd/result/failure/methods.rb +21 -0
  29. data/lib/bcdd/result/failure.rb +2 -16
  30. data/lib/bcdd/result/mixin.rb +26 -8
  31. data/lib/bcdd/result/success/methods.rb +21 -0
  32. data/lib/bcdd/result/success.rb +2 -16
  33. data/lib/bcdd/result/version.rb +1 -1
  34. data/lib/bcdd/result.rb +17 -4
  35. data/lib/bcdd-result.rb +3 -0
  36. data/sig/bcdd/result.rbs +340 -88
  37. metadata +27 -16
  38. data/lib/bcdd/result/expectations/contract/for_types_and_values.rb +0 -37
  39. data/lib/bcdd/result/expectations/contract/interface.rb +0 -21
  40. data/lib/bcdd/result/expectations/contract.rb +0 -25
  41. data/lib/result.rb +0 -5
@@ -1,37 +1,44 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class BCDD::Result::Expectations
4
- module Mixin
3
+ class BCDD::Result
4
+ module Expectations::Mixin
5
+ module Factory
6
+ def self.module!
7
+ ::Module.new do
8
+ def self.included(base); base.const_set(:ResultExpectationsMixin, self); end
9
+ def self.extended(base); base.const_set(:ResultExpectationsMixin, self); end
10
+ end
11
+ end
12
+ end
13
+
5
14
  METHODS = <<~RUBY
6
15
  def Success(...)
7
- __expected::Success(...)
16
+ _Result.Success(...)
8
17
  end
9
18
 
10
19
  def Failure(...)
11
- __expected::Failure(...)
20
+ _Result.Failure(...)
12
21
  end
13
22
 
14
23
  private
15
24
 
16
- def __expected
17
- @__expected ||= Expected.with(subject: self)
25
+ def _Result
26
+ @_Result ||= Result.with(subject: self)
18
27
  end
19
28
  RUBY
20
29
 
21
30
  module Addons
22
31
  module Continuable
23
32
  private def Continue(value)
24
- ::BCDD::Result::Success.new(type: :continued, value: value, subject: self)
33
+ Success.new(type: :continued, value: value, subject: self)
25
34
  end
26
35
  end
27
36
 
28
- OPTIONS = { Continue: Continuable }.freeze
37
+ OPTIONS = { continue: Continuable }.freeze
29
38
 
30
- def self.options(names)
31
- Array(names).filter_map { |name| OPTIONS[name] }
39
+ def self.options(config_flags)
40
+ Config::Options.addon(map: config_flags, from: OPTIONS)
32
41
  end
33
42
  end
34
43
  end
35
-
36
- private_constant :Mixin
37
44
  end
@@ -1,50 +1,65 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class BCDD::Result::Expectations
4
- require_relative 'expectations/mixin'
5
- require_relative 'expectations/error'
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
3
+ class BCDD::Result
4
+ class Expectations
5
+ require_relative 'expectations/mixin'
18
6
 
19
- def self.evaluate(data, expectations)
20
- expectations ||= Contract::NONE
7
+ def self.mixin(**options)
8
+ return mixin!(**options) if Config.instance.feature.enabled?(:expectations)
21
9
 
22
- expectations.type_and_value!(data)
10
+ result_factory_without_expectations.mixin(**options.slice(:config))
11
+ end
23
12
 
24
- TypeChecker.new(data.type, expectations: expectations)
25
- end
13
+ def self.mixin!(success: nil, failure: nil, config: nil)
14
+ addons = mixin_module::Addons.options(config)
26
15
 
27
- def initialize(subject: nil, success: nil, failure: nil, contract: nil)
28
- @subject = subject
16
+ mod = mixin_module::Factory.module!
17
+ mod.const_set(:Result, new(success: success, failure: failure, config: config).freeze)
18
+ mod.module_eval(mixin_module::METHODS)
19
+ mod.send(:include, *addons) unless addons.empty?
20
+ mod
21
+ end
29
22
 
30
- @contract = contract if contract.is_a?(Contract::Evaluator)
23
+ def self.mixin_module
24
+ Mixin
25
+ end
31
26
 
32
- @contract ||= Contract.new(success: success, failure: failure).freeze
33
- end
27
+ def self.result_factory_without_expectations
28
+ ::BCDD::Result
29
+ end
34
30
 
35
- def Success(type, value = nil)
36
- ::BCDD::Result::Success.new(type: type, value: value, subject: subject, expectations: contract)
37
- end
31
+ def self.new(...)
32
+ return result_factory_without_expectations unless Config.instance.feature.enabled?(:expectations)
38
33
 
39
- def Failure(type, value = nil)
40
- ::BCDD::Result::Failure.new(type: type, value: value, subject: subject, expectations: contract)
41
- end
34
+ instance = allocate
35
+ instance.send(:initialize, ...)
36
+ instance
37
+ end
42
38
 
43
- def with(subject:)
44
- self.class.new(subject: subject, contract: contract)
45
- end
39
+ private_class_method :mixin!, :mixin_module, :result_factory_without_expectations
40
+
41
+ def initialize(subject: nil, success: nil, failure: nil, contract: nil, config: nil)
42
+ @subject = subject
46
43
 
47
- private
44
+ @contract = contract if contract.is_a?(Contract::Evaluator)
48
45
 
49
- attr_reader :subject, :contract
46
+ @contract ||= Contract.new(success: success, failure: failure, config: config).freeze
47
+ end
48
+
49
+ def Success(type, value = nil)
50
+ Success.new(type: type, value: value, subject: subject, expectations: contract)
51
+ end
52
+
53
+ def Failure(type, value = nil)
54
+ Failure.new(type: type, value: value, subject: subject, expectations: contract)
55
+ end
56
+
57
+ def with(subject:)
58
+ self.class.new(subject: subject, contract: contract)
59
+ end
60
+
61
+ private
62
+
63
+ attr_reader :subject, :contract
64
+ end
50
65
  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
@@ -2,23 +2,9 @@
2
2
 
3
3
  class BCDD::Result
4
4
  class Failure < self
5
- def success?(_type = nil)
6
- false
7
- end
5
+ require_relative 'failure/methods'
8
6
 
9
- def failure?(type = nil)
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)
@@ -2,6 +2,15 @@
2
2
 
3
3
  class BCDD::Result
4
4
  module Mixin
5
+ module Factory
6
+ def self.module!
7
+ ::Module.new do
8
+ def self.included(base); base.const_set(:ResultMixin, self); end
9
+ def self.extended(base); base.const_set(:ResultMixin, self); end
10
+ end
11
+ end
12
+ end
13
+
5
14
  module Methods
6
15
  def Success(type, value = nil)
7
16
  Success.new(type: type, value: value, subject: self)
@@ -19,22 +28,31 @@ class BCDD::Result
19
28
  end
20
29
  end
21
30
 
22
- OPTIONS = { Continue: Continuable }.freeze
31
+ OPTIONS = { continue: Continuable }.freeze
23
32
 
24
- def self.options(names)
25
- Array(names).filter_map { |name| OPTIONS[name] }
33
+ def self.options(config_flags)
34
+ Config::Options.addon(map: config_flags, from: OPTIONS)
26
35
  end
27
36
  end
28
37
  end
29
38
 
30
- def self.mixin(with: nil)
31
- addons = Mixin::Addons.options(with)
39
+ def self.mixin(config: nil)
40
+ addons = mixin_module::Addons.options(config)
32
41
 
33
- mod = Module.new
34
- mod.send(:include, Mixin::Methods)
42
+ mod = mixin_module::Factory.module!
43
+ mod.send(:include, mixin_module::Methods)
44
+ mod.const_set(:Result, result_factory)
35
45
  mod.send(:include, *addons) unless addons.empty?
36
46
  mod
37
47
  end
38
48
 
39
- private_constant :Mixin
49
+ def self.mixin_module
50
+ Mixin
51
+ end
52
+
53
+ def self.result_factory
54
+ ::BCDD::Result
55
+ end
56
+
57
+ private_class_method :mixin_module, :result_factory
40
58
  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
@@ -2,23 +2,9 @@
2
2
 
3
3
  class BCDD::Result
4
4
  class Success < self
5
- def success?(type = nil)
6
- type.nil? || type_checker.allow_success?([type])
7
- end
5
+ require_relative 'success/methods'
8
6
 
9
- def failure?(_type = nil)
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)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module BCDD
4
4
  class Result
5
- VERSION = '0.6.0'
5
+ VERSION = '0.8.0'
6
6
  end
7
7
  end
data/lib/bcdd/result.rb CHANGED
@@ -3,11 +3,14 @@
3
3
  require_relative 'result/version'
4
4
  require_relative 'result/error'
5
5
  require_relative 'result/data'
6
+ require_relative 'result/config'
6
7
  require_relative 'result/handler'
7
8
  require_relative 'result/failure'
8
9
  require_relative 'result/success'
9
10
  require_relative 'result/mixin'
11
+ require_relative 'result/contract'
10
12
  require_relative 'result/expectations'
13
+ require_relative 'result/context'
11
14
 
12
15
  class BCDD::Result
13
16
  attr_accessor :unknown
@@ -18,10 +21,20 @@ class BCDD::Result
18
21
 
19
22
  private :unknown, :unknown=, :type_checker
20
23
 
24
+ def self.config
25
+ Config.instance
26
+ end
27
+
28
+ def self.configuration
29
+ yield(config)
30
+
31
+ config.freeze
32
+ end
33
+
21
34
  def initialize(type:, value:, subject: nil, expectations: nil)
22
35
  data = Data.new(name, type, value)
23
36
 
24
- @type_checker = Expectations.evaluate(data, expectations)
37
+ @type_checker = Contract.evaluate(data, expectations)
25
38
  @subject = subject
26
39
  @data = data
27
40
 
@@ -69,7 +82,7 @@ class BCDD::Result
69
82
  def and_then(method_name = nil, context = nil)
70
83
  return self if failure?
71
84
 
72
- method_name && block_given? and raise ArgumentError, 'method_name and block are mutually exclusive'
85
+ method_name && block_given? and raise ::ArgumentError, 'method_name and block are mutually exclusive'
73
86
 
74
87
  return call_subject_method(method_name, context) if method_name
75
88
 
@@ -129,7 +142,7 @@ class BCDD::Result
129
142
  when 0 then subject.send(method_name)
130
143
  when 1 then subject.send(method_name, value)
131
144
  when 2 then subject.send(method_name, value, context)
132
- else raise Error::WrongSubjectMethodArity.build(subject: subject, method: method)
145
+ else raise Error::InvalidSubjectMethodArity.build(subject: subject, method: method, max_arity: 2)
133
146
  end
134
147
 
135
148
  ensure_result_object(result, origin: :method)
@@ -140,6 +153,6 @@ class BCDD::Result
140
153
 
141
154
  return result if result.subject.equal?(subject)
142
155
 
143
- raise Error::WrongResultSubject.build(given_result: result, expected_subject: subject)
156
+ raise Error::InvalidResultSubject.build(given_result: result, expected_subject: subject)
144
157
  end
145
158
  end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bcdd/result'