Skip to content
This repository has been archived by the owner on Jun 1, 2023. It is now read-only.

class ShopifyCli::Result::Failure

Kevin O'Sullivan edited this page Jun 28, 2021 · 3 revisions

Implements a container for wrapping an error value. In many cases, the error value is going to be an exception but other values are fully supported:

Failure
  .new(RuntimeError.new("Something went wrong"))
  .error # => RuntimeError.new

Failure
  .new("Something went wrong")
  .error # => "Something went wrong"

Failure does not support transformations with then and map. When any of these two methods is invoked on a Failure, the Failure itself is returned unless it is rescued from or unwrapped. This enables the caller to build optimistic transformation chains and defer error handling:

Failure
  .new(nil)
  .then { |json| JSON.parse(json) }                      # Ignored
  .then(&:with_indifferent_access)                       # Ignored
  .then { |data| data.values_at(:firstname, :lastname) } # Ignored
  .unwrap(Person.new("John", "Doe"))                     # => Person

Alternatively, we could rescue from the error and then proceed with the remaining transformations:

Person = Struct.new(:firstname, :lastname)
Failure
  .new(nil)
  .then { |json| JSON.parse(json) }                      # Ignored
  .then(&:with_indifferent_access)                       # Ignored
  .rescue { {firstname: "John", lastname: "Doe" }}
  .then { |data| data.values_at(:firstname, :lastname) } # Executed
  .then { |members| Person.new(*members) }               # Executed
  .unwrap(nil)                                           # => Person

Attributes

  • error

Class Methods

new

new(error) initializes a new Failure from an arbitrary value. In many cases, this value is going to be an instance of a subclass of Exception but any type is supported.

see source

# File lib/shopify-cli/result.rb, line 245
def initialize(error)
  @error = error
end

Instance Methods

success?

success?() always returns false to indicate that this result represents a failure.

see source

# File lib/shopify-cli/result.rb, line 252
def success?
  false
end

failure?

failure?() Always returns true to indicate that this result represents a failure.

see source

# File lib/shopify-cli/result.rb, line 259
def failure?
  true
end

value

value() raises an ShopifyCli::Result::UnexpectedError as a ShopifyCli::Result::Failure does not carry a success value.

see source

# File lib/shopify-cli/result.rb, line 267
def value
  raise UnexpectedFailure
end

map

map() is a no-op and simply returns itself. This is essential to skip transformation steps in a chain once an error has occurred.

see source

# File lib/shopify-cli/result.rb, line 275
def map
  self
end

then

then() is a no-op and simply returns itself. This is essential to skip transformation steps in a chain once an error has occurred.

see source

# File lib/shopify-cli/result.rb, line 283
def then
  self
end

rescue

rescue(&block) can be used to recover from a failure or produce a new failure with a different error.

Failure
  .new("Something went wrong")
  .rescue { |msg| [msg, "but we fixed it!"].join(" "") }
  .tap do |result|
     result.success? # => true
     result.value # => "Something went wrong but we fixed it!"
  end

rescue is opinionated when it comes to the return value of the block. If the return value is an Exception – either one that was raised or an instance of a subclass of Exception – a Failure is returned. Any other value results in a Success unless the value has been explicitly wrapped in a Failure:

Failure
  .new(RuntimeError.new)
  .rescue { "All good! "}
  .success? # => true

Failure
  .new(RuntimeError.new)
  .rescue { Failure.new("Still broken!") }
  .success? # => false
see source

# File lib/shopify-cli/result.rb, line 315
def rescue(&block)
  Result.wrap(&block).call(@error)
end

unwrap

unwrap(*args, &block) returns the fallback value specified by the caller. The fallback value can be provided as a method argument or as a block. If a block is given, it receives the error as its first and only argument:

failure = Failure.new(RuntimeError.new("Something went wrong!"))

failure.unwrap(nil) # => nil
failure.unwrap { |e| e.message } # => "Something went wrong!"

Parameters

  • *args should be an Array with zero or one element
  • &block should be a Proc that takes zero or one argument

Raises

  • ArgumentError if both a fallback argument and a block is provided
see source

# File lib/shopify-cli/result.rb, line 338
def unwrap(*args, &block)
  raise ArgumentError, "expected either a fallback value or a block" unless (args.length == 1) ^ block
  block ? block.call(@error) : args.pop
end

Clone this wiki locally