Class: SorbetOperation::Result
- Inherits:
-
Object
- Object
- SorbetOperation::Result
- Extended by:
- T::Generic, T::Sig
- Defined in:
- lib/sorbet_operation/result.rb
Overview
Constant Summary collapse
- ValueType =
The type of the value wrapped by the SorbetOperation::Result. The type can be any valid Sorbet type, as long as it’s a subtype of
Object. type_member { { upper: Object } }
Instance Method Summary collapse
-
#casted_value ⇒ ValueType
private
A word of explanation as to why this is necessary: the
valueargument inResult‘s constructor is typed asT.nilable(ValueType), because it will benilfor failure results. -
#failure? ⇒ Boolean
Returns
trueif the result is a failure. -
#initialize(success, value, error) ⇒ void
constructor
Constructs a new Result, either a success or a failure.
-
#on_failure(&blk) {|T.must(@error)| ... } ⇒ T.self_type
Yields the contained error if the result is a failure, otherwise does nothing.
-
#on_success(&blk) {|casted_value| ... } ⇒ T.self_type
Yields the contained value if the result is a success, otherwise does nothing.
-
#safe_unwrap ⇒ ValueType?
Returns the contained value if the result is a success, otherwise returns
nil. -
#safe_unwrap_error ⇒ Failure?
Returns the contained error if the result is a failure, otherwise returns
nil. -
#success? ⇒ Boolean
Returns
trueif the result is a success. -
#unwrap! ⇒ ValueType
Returns the contained value if the result is a success, otherwise raises the contained error.
-
#unwrap_error! ⇒ Failure
Returns the contained error if the result is a failure, otherwise raises an error.
-
#unwrap_or(default) ⇒ ValueType
Returns the contained value if the result is a success, otherwise returns the provided default value.
-
#unwrap_or_else(&blk) {|T.must(@error)| ... } ⇒ ValueType
Returns the contained value if the result is a success, otherwise calls the block with the contained error and returns the block’s return value.
Constructor Details
#initialize(success, value, error) ⇒ void
Constructs a new SorbetOperation::Result, either a success or a failure.
If success is true, then value must be provided (although it can be nil, because ValueType may be nilable) and error must be nil.
If success is false, then value must be nil and error must be non-nil.
Calling this constructor directly should rarely be necessary. In normal usage, Base#perform will return a SorbetOperation::Result for you.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/sorbet_operation/result.rb', line 36 def initialize(success, value, error) @success = success @value = value @error = error # NOTE: these checks are annoying. A better API would be to make this # constructor private and provide two factory methods: # - `Result.success(value)` # - `Result.failure(error)` # # However, in order to do this, we would need to be able to use # {ValueType} in class methods. At this time, there is no way to tell # Sorbet that a generic type applies to both the class and its # singleton. We would need to duplicate the value type: # ``` # ValueTypeMember = type_member { { upper: Object } } # ValueTypeTemplate = type_template { { upper: Object } } # ``` # and every subclass would need to specify both (and ensure that # they're both set to the same type). This would be quite clumsy. Since # `Result` should rarely be instantiated directly (rather, it's # instantiated by `SorbetOperation::Base#perform`), we'll just live with # this less than ideal API for now. if @success # We can't test that value is not nil because the value type can be # nilable. (In theory we could check if the type is nilable and only # apply the check if it's not, but that's not worth the complexity.) unless error.nil? raise ArgumentError, "Cannot pass an error to a success result" end elsif error.nil? raise ArgumentError, "Must pass an error to a failure result" elsif !value.nil? raise ArgumentError, "Cannot pass a value to a failure result" end end |
Instance Method Details
#casted_value ⇒ ValueType (private)
A word of explanation as to why this is necessary: the value argument in Result‘s constructor is typed as T.nilable(ValueType), because it will be nil for failure results.
The signatures for unwrap!, unwrap_or_else, and on_success all use (non-nilable) ValueType because in those cases, we know that the result is a success.
However, ValueType can be nilable, in which case nil is a valid value for a success result. As a result, we can’t just wrap value in T.must. Instead, we cast @value from T.nilable(ValueType) to ValueType, which is ~the same thing as T.must but doesn’t raise a runtime error if ValueType is nilable and @value is nil.
There’s probably a better way to handle this.
198 199 200 |
# File 'lib/sorbet_operation/result.rb', line 198 def casted_value T.cast(@value, ValueType) end |
#failure? ⇒ Boolean
Returns true if the result is a failure.
81 82 83 |
# File 'lib/sorbet_operation/result.rb', line 81 def failure? !success? end |
#on_failure(&blk) {|T.must(@error)| ... } ⇒ T.self_type
Yields the contained error if the result is a failure, otherwise does nothing. Returns self so this call can be chained to #on_success.
173 174 175 176 |
# File 'lib/sorbet_operation/result.rb', line 173 def on_failure(&blk) yield(T.must(@error)) if failure? self end |
#on_success(&blk) {|casted_value| ... } ⇒ T.self_type
Yields the contained value if the result is a success, otherwise does nothing. Returns self so this call can be chained to #on_failure.
160 161 162 163 |
# File 'lib/sorbet_operation/result.rb', line 160 def on_success(&blk) yield(casted_value) if success? self end |
#safe_unwrap ⇒ ValueType?
Returns the contained value if the result is a success, otherwise returns nil.
97 98 99 100 101 |
# File 'lib/sorbet_operation/result.rb', line 97 def safe_unwrap return if failure? casted_value end |
#safe_unwrap_error ⇒ Failure?
Returns the contained error if the result is a failure, otherwise returns nil.
146 147 148 149 150 |
# File 'lib/sorbet_operation/result.rb', line 146 def safe_unwrap_error return T.must(@error) if failure? nil end |
#success? ⇒ Boolean
Returns true if the result is a success.
75 76 77 |
# File 'lib/sorbet_operation/result.rb', line 75 def success? @success end |
#unwrap! ⇒ ValueType
Returns the contained value if the result is a success, otherwise raises the contained error.
88 89 90 91 92 |
# File 'lib/sorbet_operation/result.rb', line 88 def unwrap! raise T.must(@error) if failure? casted_value end |
#unwrap_error! ⇒ Failure
Returns the contained error if the result is a failure, otherwise raises an error.
136 137 138 139 140 141 |
# File 'lib/sorbet_operation/result.rb', line 136 def unwrap_error! return T.must(@error) if failure? # TODO: custom error type? raise "Called `unwrap_err!` on a success" end |
#unwrap_or(default) ⇒ ValueType
Returns the contained value if the result is a success, otherwise returns the provided default value.
112 113 114 115 116 |
# File 'lib/sorbet_operation/result.rb', line 112 def unwrap_or(default) return casted_value if success? default end |
#unwrap_or_else(&blk) {|T.must(@error)| ... } ⇒ ValueType
Returns the contained value if the result is a success, otherwise calls the block with the contained error and returns the block’s return value.
127 128 129 130 131 |
# File 'lib/sorbet_operation/result.rb', line 127 def unwrap_or_else(&blk) return casted_value if success? yield(T.must(@error)) end |