Class: Object

Inherits:
BasicObject
Defined in:
lib/errgonomic/result.rb,
lib/errgonomic/type.rb,
lib/errgonomic/presence.rb,
lib/errgonomic/core_ext/blank.rb

Overview

Introduce certain helper methods into the Object class.

Examples:

"foo".result? # => false
"foo".assert_result! # => raise Errgonomic::ResultRequiredError

Instance Method Summary collapse

Instance Method Details

#assert_result!Object

Lacking static typing, we are going to want to make it easy to enforce at runtime that a given object is a Result.

Examples:

"foo".assert_result! # => raise Errgonomic::ResultRequiredError
Ok("foo").assert_result! # => true

Raises:



301
302
303
304
305
# File 'lib/errgonomic/result.rb', line 301

def assert_result!
  return true if result?

  raise Errgonomic::ResultRequiredError
end

#blank?true, false

An object is blank if it’s false, empty, or a whitespace string. For example, nil, ”, ‘ ’, [], {}, and false are all blank.

This simplifies

!address || address.empty?

to

address.blank?

Returns:

  • (true, false)


18
19
20
# File 'lib/errgonomic/core_ext/blank.rb', line 18

def blank?
  respond_to?(:empty?) ? !!empty? : false
end

#blank_or(value) ⇒ Object

Returns the receiver if it is blank, otherwise returns the given value.

Parameters:

  • value (Object)

    The value to return if the receiver is not blank.

Returns:

  • (Object)

    The receiver if it is blank, otherwise the given value.



70
71
72
73
74
75
76
77
78
79
80
# File 'lib/errgonomic/presence.rb', line 70

def blank_or(value)
  # TBD whether this is *too* strict
  if value.class != self.class && self.class != NilClass
    raise Errgonomic::TypeMismatchError,
          "Type mismatch: default value is a #{value.class} but original was a #{self.class}"
  end

  return self if blank?

  value
end

#blank_or_else(&block) ⇒ Object

Returns the receiver if it is blank, otherwise returns the result of the block.

Parameters:

  • block (Proc)

    The block to call if the receiver is not blank.

Returns:

  • (Object)

    The receiver if it is blank, otherwise the result of the block.



87
88
89
90
91
# File 'lib/errgonomic/presence.rb', line 87

def blank_or_else(&block)
  return block.call unless blank?

  self
end

#blank_or_raise!(message) ⇒ Object Also known as: blank_or_raise

Returns the receiver if it is blank, otherwise raises a NotPresentError. This method is helpful to enforce expectations where blank objects are required.

Parameters:

  • message (String)

    The error message to raise if the receiver is not blank.

Returns:

  • (Object)

    The receiver if it is blank, otherwise raises a NotPresentError.

Raises:



58
59
60
61
62
# File 'lib/errgonomic/presence.rb', line 58

def blank_or_raise!(message)
  raise Errgonomic::NotPresentError, message unless blank?

  self
end

#not_type_or_raise!(type, message = nil) ⇒ Object

Returns the receiver if it does not match the expected type, otherwise raises a TypeMismatchError.

Examples:

'hello'.not_type_or_raise!(Integer) #=> "hello"
123.not_type_or_raise!(Integer, "We dont want an integer!") #=> raise Errgonomic::TypeMismatchError, "We dont want an integer!"
123.not_type_or_raise!(Integer) #=> raise Errgonomic::TypeMismatchError, "Expected anything but Integer but got Integer"

Parameters:

  • type (Class)

    The type or module the receiver should not be.

  • message (String) (defaults to: nil)

    Optional error message to raise if type matches.

Returns:

  • (Object)

    The receiver if it is not of the specified type.

Raises:



61
62
63
64
65
66
# File 'lib/errgonomic/type.rb', line 61

def not_type_or_raise!(type, message = nil)
  message ||= "Expected anything but #{type} but got #{self.class}"
  raise Errgonomic::TypeMismatchError, message if is_a?(type)

  self
end

#presenceObject

Returns the receiver if it’s present otherwise returns nil. object.presence is equivalent to

object.present? ? object : nil

For example, something like

state   = params[:state]   if params[:state].present?
country = params[:country] if params[:country].present?
region  = state || country || 'US'

becomes

region = params[:state].presence || params[:country].presence || 'US'

Returns:



45
46
47
# File 'lib/errgonomic/core_ext/blank.rb', line 45

def presence
  self if present?
end

#present?true, false

An object is present if it’s not blank.

Returns:

  • (true, false)


25
26
27
# File 'lib/errgonomic/core_ext/blank.rb', line 25

def present?
  !blank?
end

#present_or(value) ⇒ Object

Returns the receiver if it is present, otherwise returns the given value. If constructing the default value is expensive, consider using present_or_else.

Parameters:

  • value (Object)

    The value to return if the receiver is not present.

Returns:

  • (Object)

    The receiver if it is present, otherwise the given value.



29
30
31
32
33
34
35
36
37
38
39
# File 'lib/errgonomic/presence.rb', line 29

def present_or(value)
  # TBD whether this is *too* strict
  if value.class != self.class && self.class != NilClass
    raise Errgonomic::TypeMismatchError,
          "Type mismatch: default value is a #{value.class} but original was a #{self.class}"
  end

  return self if present?

  value
end

#present_or_else(&block) ⇒ Object

Returns the receiver if it is present, otherwise returns the result of the block. Invoking a block may be preferable to returning a default value with present_or, if constructing the default value is expensive.

Parameters:

  • block (Proc)

    The block to call if the receiver is not present.

Returns:

  • (Object)

    The receiver if it is present, otherwise the result of the block.



47
48
49
50
51
# File 'lib/errgonomic/presence.rb', line 47

def present_or_else(&block)
  return block.call if blank?

  self
end

#present_or_raise!(message) ⇒ Object Also known as: present_or_raise

Returns the receiver if it is present, otherwise raises a NotPresentError. This method is useful to enforce strong expectations, where it is preferable to fail early rather than risk causing an ambiguous error somewhere else.

Parameters:

  • message (String)

    The error message to raise if the receiver is not present.

Returns:

  • (Object)

    The receiver if it is present, otherwise raises a NotPresentError.

Raises:



15
16
17
18
19
# File 'lib/errgonomic/presence.rb', line 15

def present_or_raise!(message)
  raise Errgonomic::NotPresentError, message if blank?

  self
end

#result?Boolean

Convenience method to indicate whether we are working with a result. TBD whether we implement some stubs for the rest of the Result API; I want to think about how effectively these map to truthiness or presence.

Examples:

"foo".result? # => false
Ok("foo").result? # => true

Returns:

  • (Boolean)


291
292
293
# File 'lib/errgonomic/result.rb', line 291

def result?
  false
end

#type_or(type, default) ⇒ Object

Returns the receiver if it matches the expected type, otherwise returns the default value.

Examples:

'hello'.type_or(String, 'default')  # => "hello"
123.type_or(String, 'default')      # => "default"

Parameters:

  • type (Class)

    The expected type or module the receiver should be.

  • default (Object)

    The value to return if type doesn’t match.

Returns:

  • (Object)

    The receiver if it is of the expected type, otherwise the default value.



31
32
33
34
35
# File 'lib/errgonomic/type.rb', line 31

def type_or(type, default)
  return self if is_a?(type)

  default
end

#type_or_else(type, &block) ⇒ Object

Returns the receiver if it matches the expected type, otherwise returns the result of the block. Useful when constructing the default value is expensive.

Examples:

'hello'.type_or_else(String) { 'default' }  # => "hello"
123.type_or_else(String) { 'default' }      # => "default"

Parameters:

  • type (Class)

    The expected type or module the receiver should be.

  • block (Proc)

    The block to call if type doesn’t match.

Returns:

  • (Object)

    The receiver if it is of the expected type, otherwise the block result.



46
47
48
49
50
# File 'lib/errgonomic/type.rb', line 46

def type_or_else(type, &block)
  return self if is_a?(type)

  block.call
end

#type_or_raise!(type, message = nil) ⇒ Object Also known as: type_or_raise

Returns the receiver if it matches the expected type, otherwise raises a TypeMismatchError. This is useful for enforcing type expectations in method arguments.

Examples:

'hello'.type_or_raise!(String) #=> "hello"
123.type_or_raise!(String, "We need a string!") #=> raise Errgonomic::TypeMismatchError, "We need a string!"
123.type_or_raise!(String) #=> raise Errgonomic::TypeMismatchError, "Expected String but got Integer"

Parameters:

  • type (Class)

    The expected type or module the receiver should be.

  • message (String) (defaults to: nil)

    Optional error message to raise if type doesn’t match.

Returns:

  • (Object)

    The receiver if it is of the expected type.

Raises:



14
15
16
17
18
19
# File 'lib/errgonomic/type.rb', line 14

def type_or_raise!(type, message = nil)
  message ||= "Expected #{type} but got #{self.class}"
  raise Errgonomic::TypeMismatchError, message unless is_a?(type)

  self
end