Class: Statefully::State Abstract

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Enumerable
Defined in:
lib/statefully/state.rb

Overview

This class is abstract.

State is an immutable collection of fields with some convenience methods.

Direct Known Subclasses

Failure, Finished, None, Success

Defined Under Namespace

Classes: Failure, Finished, None, Success

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

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

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Dynamically pass unknown messages to the underlying state storage

State fields become accessible through readers, like in an OpenStruct. A single state field can be questioned for existence by having its name followed by a question mark - eg. bacon?. A single state field can be force-accessed by having its name followed by an exclamation mark - eg. bacon!.

This method reeks of :reek:TooManyStatements.

Examples:

state = Statefully::State.create(bacon: 'tasty')

state.bacon
=> "tasty"

state.bacon?
=> true

state.bacon!
=> "tasty"

state.cabbage
NoMethodError: undefined method `cabbage' for #<Statefully::State::Success bacon="tasty">
        [STACK TRACE]

state.cabbage?
=> false

state.cabbage!
Statefully::Errors::StateMissing: field 'cabbage' missing from state
        [STACK TRACE]

Parameters:

  • name (Symbol|String)
  • args (Array<Object>)
  • block (Proc)

Returns:

  • (Object)

Raises:


260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/statefully/state.rb', line 260

def method_missing(name, *args, &block)
  sym_name = name.to_sym
  return fetch(sym_name) if key?(sym_name)
  str_name = name.to_s
  modifier = str_name[-1]
  return super unless %w[? !].include?(modifier)
  base = str_name[0...-1].to_sym
  known = key?(base)
  return known if modifier == '?'
  return fetch(base) if known
  raise Errors::StateMissing, base
end

Instance Attribute Details

#previousState (readonly)

Return the previous Statefully::State

Examples:

Statefully::State.create.previous
=> #<Statefully::State::None>

Statefully::State.create.succeed.previous
=> #<Statefully::State::Success>

Returns:


22
23
24
# File 'lib/statefully/state.rb', line 22

def previous
  @previous
end

Class Method Details

.create(**values) ⇒ type

Create an instance of Statefully::State object

This is meant as the only valid way of creating Statefully::State objects.

Examples:

Statefully::State.create(key: 'val')
=> #<Statefully::State::Success key="val">

Parameters:

  • values (Hash<Symbol, Object>)

    keyword arguments

Returns:

  • (type)
    description

68
69
70
# File 'lib/statefully/state.rb', line 68

def self.create(**values)
  Success.send(:new, values, previous: None.instance).freeze
end

Instance Method Details

#diffDiff

Return a Diff between current and previous Statefully::State

Examples:

Statefully::State.create.succeed(key: 'val').diff
=> #<Statefully::Diff::Changed added={key: "val"}>

Returns:


79
80
81
# File 'lib/statefully/state.rb', line 79

def diff
  Diff.create(current: self, previous: previous)
end

#eachEnumerator

Examples:

Statefully::State.create(key: 'val').each { |key, val| puts("#{key} => #{val}") }
key => val

Returns:

  • (Enumerator)

See Also:


55
# File 'lib/statefully/state.rb', line 55

def_delegators :@_members, :each, :fetch, :key?, :keys

#failed?Boolean

Check if the current Statefully::State is failed

Examples:

state = Statefully::State.create
state.failed?
=> false

state.fail(RuntimeError.new('Boom!')).failed?
=> true

Returns:

  • (Boolean)

120
121
122
# File 'lib/statefully/state.rb', line 120

def failed?
  !successful?
end

#fetchObject

Examples:

Statefully::State.create(key: 'val').fetch(:key)
=> 'val'

Returns:

  • (Object)

See Also:


55
# File 'lib/statefully/state.rb', line 55

def_delegators :@_members, :each, :fetch, :key?, :keys

#finished?Boolean

Check if the current Statefully::State is finished

Examples:

state = Statefully::State.create
state.finished?
=> false

state.finish.finished?
=> true

Returns:

  • (Boolean)

135
136
137
# File 'lib/statefully/state.rb', line 135

def finished?
  false
end

#historyArray<Diff>

Return all historical changes to this Statefully::State

Examples:

Statefully::State.create.succeed(key: 'val').history
=> [#<Statefully::Diff::Changed added={key: "val"}>, #<Statefully::Diff::Created>]

Returns:


90
91
92
# File 'lib/statefully/state.rb', line 90

def history
  ([diff] + previous.history).freeze
end

#inspectString

Show the current Statefully::State in a human-readable form

Examples:

Statefully::State.create(key: 'val')
=> #<Statefully::State::Success key="val">

Returns:

  • (String)

181
182
183
# File 'lib/statefully/state.rb', line 181

def inspect
  _inspect_details({})
end

#key?Boolean

Examples:

state = Statefully::State.create(key: 'val')
state.key?(:key)
=> true
state.key?(:other)
=> false

Returns:

  • (Boolean)

See Also:


55
# File 'lib/statefully/state.rb', line 55

def_delegators :@_members, :each, :fetch, :key?, :keys

#keysArray<Symbol>

Examples:

Statefully::State.create(key: 'val').keys
=> [:key]

Returns:

  • (Array<Symbol>)

See Also:


55
# File 'lib/statefully/state.rb', line 55

def_delegators :@_members, :each, :fetch, :key?, :keys

#none?Boolean

Check if the current Statefully::State is none (a null-object of Statefully::State)

Examples:

state = Statefully::State.create
state.none?
=> false

state.previous.none?
=> true

Returns:

  • (Boolean)

150
151
152
# File 'lib/statefully/state.rb', line 150

def none?
  false
end

#resolveState

Resolve the current Statefully::State

Resolving will return the current Statefully::State if successful, but raise an error wrapped in a Failure. This is a convenience method inspired by monadic composition from functional languages.

Examples:

Statefully::State.create(key: 'val').resolve
=> #<Statefully::State::Success key="val">

Statefully::State.create.fail(RuntimeError.new('Boom!')).resolve
RuntimeError: Boom!
        [STACK TRACE]

Returns:

Raises:

  • (StandardError)

    if the receiver is #failed?


170
171
172
# File 'lib/statefully/state.rb', line 170

def resolve
  self
end

#successful?Boolean

Check if the current Statefully::State is successful

Examples:

state = Statefully::State.create
state.successful?
=> true

state.fail(RuntimeError.new('Boom!')).successful?
=> false

Returns:

  • (Boolean)

105
106
107
# File 'lib/statefully/state.rb', line 105

def successful?
  true
end