Class: Solid::Result

Inherits:
Object
  • Object
show all
Defined in:
lib/solid/result.rb,
lib/solid/result/data.rb,
lib/solid/result/_self.rb,
lib/solid/result/mixin.rb,
lib/solid/result/config.rb,
lib/solid/result/failure.rb,
lib/solid/result/handler.rb,
lib/solid/result/success.rb,
lib/solid/result/version.rb,
lib/solid/result/event_logs.rb,
lib/solid/result/expectations.rb,
lib/solid/result/ignored_types.rb,
lib/solid/result/config/options.rb,
lib/solid/result/config/switcher.rb,
lib/solid/result/event_logs/tree.rb,
lib/solid/result/callable_and_then.rb,
lib/solid/result/contract/disabled.rb,
lib/solid/result/contract/evaluator.rb,
lib/solid/result/contract/for_types.rb,
lib/solid/result/contract/interface.rb,
lib/solid/result/expectations/mixin.rb,
lib/solid/result/event_logs/tracking.rb,
lib/solid/result/handler/allowed_types.rb,
lib/solid/result/callable_and_then/error.rb,
lib/solid/result/config/switchers/addons.rb,
lib/solid/result/callable_and_then/caller.rb,
lib/solid/result/callable_and_then/config.rb,
lib/solid/result/config/switchers/features.rb,
lib/solid/result/contract/for_types_and_values.rb,
lib/solid/result/config/switchers/constant_aliases.rb,
lib/solid/result/config/switchers/pattern_matching.rb

Direct Known Subclasses

Output, Failure, Success

Defined Under Namespace

Modules: CallableAndThen, Contract, EventLogs, IgnoredTypes, Mixin Classes: Config, Error, Expectations, Failure, Success

Constant Summary collapse

TYPE_AND_VALUE =
%i[type value].freeze
VERSION =
'2.0.0'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type:, value:, source: nil, expectations: nil, terminal: nil) ⇒ Result

Returns a new instance of Result.



22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/solid/result/_self.rb', line 22

def initialize(type:, value:, source: nil, expectations: nil, terminal: nil)
  data = Data.new(kind, type, value)

  @type_checker = Contract.evaluate(data, expectations)
  @source = source
  @terminal = kind == :failure || (terminal && !IgnoredTypes.include?(type))
  @data = data

  self.unknown = true
  self.event_logs = EventLogs::Tracking::EMPTY

  EventLogs.tracking.record(self)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object



132
133
134
# File 'lib/solid/result/_self.rb', line 132

def method_missing(name, *args, &block)
  name.end_with?('?') ? is?(name.to_s.chomp('?')) : super
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



6
7
8
# File 'lib/solid/result/_self.rb', line 6

def data
  @data
end

#event_logsObject

Returns the value of attribute event_logs.



4
5
6
# File 'lib/solid/result/_self.rb', line 4

def event_logs
  @event_logs
end

#terminalObject (readonly)

Returns the value of attribute terminal.



6
7
8
# File 'lib/solid/result/_self.rb', line 6

def terminal
  @terminal
end

Class Method Details

.configObject



12
13
14
# File 'lib/solid/result/_self.rb', line 12

def self.config
  Config.instance
end

.configuration(freeze: true) {|config| ... } ⇒ Object

Yields:



16
17
18
19
20
# File 'lib/solid/result/_self.rb', line 16

def self.configuration(freeze: true)
  yield(config)

  freeze and config.freeze
end

.event_logs(name: nil, desc: nil, &block) ⇒ Object



24
25
26
# File 'lib/solid/result/event_logs.rb', line 24

def self.event_logs(name: nil, desc: nil, &block)
  EventLogs.tracking.exec(name, desc, &block)
end

.Failure(type, value = nil) ⇒ Object



8
9
10
# File 'lib/solid/result/failure.rb', line 8

def self.Failure(type, value = nil)
  Failure.new(type: type, value: value)
end

.mixin(config: nil) ⇒ Object



53
54
55
56
57
58
59
60
61
# File 'lib/solid/result/mixin.rb', line 53

def self.mixin(config: nil)
  addons = mixin_module::Addons.options(config)

  mod = mixin_module::Factory.module!
  mod.send(:include, mixin_module::Methods)
  mod.const_set(:Result, result_factory)
  mod.send(:include, *addons.values) unless addons.empty?
  mod
end

.Success(type, value = nil) ⇒ Object



8
9
10
# File 'lib/solid/result/success.rb', line 8

def self.Success(type, value = nil)
  Success.new(type: type, value: value)
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



106
107
108
# File 'lib/solid/result/_self.rb', line 106

def ==(other)
  self.class == other.class && type == other.type && value == other.value
end

#and_then(method_name = nil, injected_value = nil, &block) ⇒ Object



82
83
84
85
86
87
88
# File 'lib/solid/result/_self.rb', line 82

def and_then(method_name = nil, injected_value = nil, &block)
  return self if terminal?

  method_name && block and raise ::ArgumentError, 'method_name and block are mutually exclusive'

  method_name ? call_and_then_source_method(method_name, injected_value) : call_and_then_block(block)
end

#and_then!(source, injected_value = nil, _call: nil) ⇒ Object



90
91
92
93
94
95
96
# File 'lib/solid/result/_self.rb', line 90

def and_then!(source, injected_value = nil, _call: nil)
  raise Error::CallableAndThenDisabled unless Config.instance.feature.enabled?(:and_then!)

  return self if terminal?

  call_and_then_callable!(source, value: value, injected_value: injected_value, method_name: _call)
end

#deconstructObject



118
119
120
# File 'lib/solid/result/_self.rb', line 118

def deconstruct
  [type, value]
end

#deconstruct_keys(keys) ⇒ Object



124
125
126
127
128
129
130
# File 'lib/solid/result/_self.rb', line 124

def deconstruct_keys(keys)
  output = TYPE_AND_VALUE.each_with_object({}) do |key, hash|
    hash[key] = send(key) if keys.include?(key)
  end

  output.empty? ? value : output
end

#failure?(_type = nil) ⇒ Boolean

Returns:

  • (Boolean)

Raises:



56
57
58
# File 'lib/solid/result/_self.rb', line 56

def failure?(_type = nil)
  raise Error::NotImplemented
end

#handle {|handler| ... } ⇒ Object

Yields:

  • (handler)


98
99
100
101
102
103
104
# File 'lib/solid/result/_self.rb', line 98

def handle
  handler = Handler.new(self, type_checker: type_checker)

  yield handler

  handler.send(:outcome)
end

#hashObject



110
111
112
# File 'lib/solid/result/_self.rb', line 110

def hash
  [self.class, type, value].hash
end

#inspectObject



114
115
116
# File 'lib/solid/result/_self.rb', line 114

def inspect
  format('#<%<class_name>s type=%<type>p value=%<value>p>', class_name: self.class.name, type: type, value: value)
end

#on(*types, &block) ⇒ Object Also known as: on_type



64
65
66
67
68
# File 'lib/solid/result/_self.rb', line 64

def on(*types, &block)
  raise Error::MissingTypeArgument if types.empty?

  tap { known(block) if type_checker.allow?(types) }
end

#on_failure(*types, &block) ⇒ Object



74
75
76
# File 'lib/solid/result/_self.rb', line 74

def on_failure(*types, &block)
  tap { known(block) if type_checker.allow_failure?(types) && failure? }
end

#on_success(*types, &block) ⇒ Object



70
71
72
# File 'lib/solid/result/_self.rb', line 70

def on_success(*types, &block)
  tap { known(block) if type_checker.allow_success?(types) && success? }
end

#on_unknownObject



78
79
80
# File 'lib/solid/result/_self.rb', line 78

def on_unknown
  tap { yield(value, type) if unknown }
end

#respond_to_missing?(name, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


136
137
138
# File 'lib/solid/result/_self.rb', line 136

def respond_to_missing?(name, include_private = false)
  name.end_with?('?') || super
end

#success?(_type = nil) ⇒ Boolean

Returns:

  • (Boolean)

Raises:



52
53
54
# File 'lib/solid/result/_self.rb', line 52

def success?(_type = nil)
  raise Error::NotImplemented
end

#terminal?Boolean

Returns:

  • (Boolean)


36
37
38
# File 'lib/solid/result/_self.rb', line 36

def terminal?
  terminal
end

#typeObject



40
41
42
# File 'lib/solid/result/_self.rb', line 40

def type
  data.type
end

#type?(arg) ⇒ Boolean Also known as: is?

Returns:

  • (Boolean)


48
49
50
# File 'lib/solid/result/_self.rb', line 48

def type?(arg)
  type_checker.allow!(arg.to_sym) == type
end

#valueObject



44
45
46
# File 'lib/solid/result/_self.rb', line 44

def value
  data.value
end

#value_or(&_block) ⇒ Object



60
61
62
# File 'lib/solid/result/_self.rb', line 60

def value_or(&_block)
  raise Error::NotImplemented
end