Class: Nanomachine
- Inherits:
-
Object
- Object
- Nanomachine
- Defined in:
- lib/nanomachine.rb,
lib/nanomachine/version.rb
Overview
A minimal state machine where you transition between states, instead of transition by input symbols or events.
Constant Summary collapse
- InvalidTransitionError =
Raised when a transition cannot be performed.
Class.new(StandardError)
- InvalidStateError =
Raised when a given state cannot be accepted.
Class.new(StandardError)
- VERSION =
"1.0.1"
Instance Attribute Summary collapse
-
#state ⇒ String
readonly
Current state of the state machine.
-
#transitions ⇒ Hash<String, Set>
readonly
Mapping of state to possible transition targets.
Instance Method Summary collapse
-
#initialize(initial_state) {|self| ... } ⇒ Nanomachine
constructor
Construct a Nanomachine with an initial state.
-
#on_transition(options = {}) {|transition, *args, &block| ... } ⇒ Object
Define a callback to be executed on transition.
-
#transition(from, to) ⇒ Object
Define possible state transitions from the source state.
-
#transition_to(other_state, *args, &block) ⇒ String, false
Transition the state machine from the current state to a target state.
-
#transition_to!(other_state) ⇒ String
Same as #transition_to, but raises an error if the transition is not allowed.
Constructor Details
#initialize(initial_state) {|self| ... } ⇒ Nanomachine
Construct a Nanomachine with an initial state.
56 57 58 59 60 61 62 63 64 65 |
# File 'lib/nanomachine.rb', line 56 def initialize(initial_state) if initial_state.nil? raise InvalidStateError, "initial state cannot be nil" end @state = initial_state.to_s @transitions = Hash.new(Set.new) @callbacks = Hash.new { |h, k| h[k] = [] } yield self if block_given? end |
Instance Attribute Details
#state ⇒ String (readonly)
Returns current state of the state machine.
68 69 70 |
# File 'lib/nanomachine.rb', line 68 def state @state end |
#transitions ⇒ Hash<String, Set> (readonly)
Returns mapping of state to possible transition targets.
76 77 78 |
# File 'lib/nanomachine.rb', line 76 def transitions @transitions end |
Instance Method Details
#on_transition(options = {}) {|transition, *args, &block| ... } ⇒ Object
Define a callback to be executed on transition.
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/nanomachine.rb', line 122 def on_transition( = {}, &block) unless block_given? raise LocalJumpError, "no block given" end from = .delete(:from) from &&= from.to_s to = .delete(:to) to &&= to.to_s unless .empty? raise ArgumentError, "unknown options: #{.keys.join(", ")}" end @callbacks[[from, to]] << block end |
#transition(from, to) ⇒ Object
Define possible state transitions from the source state.
87 88 89 |
# File 'lib/nanomachine.rb', line 87 def transition(from, to) transitions[from.to_s] = Set.new(to).map!(&:to_s) end |
#transition_to(other_state, *args, &block) ⇒ String, false
Transition the state machine from the current state to a target state.
153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/nanomachine.rb', line 153 def transition_to(other_state, *args, &block) other_state &&= other_state.to_s if transitions[state].include?(other_state) previous_state, @state = @state, other_state [[nil, nil], [previous_state, nil], [nil, @state], [previous_state, @state]].each do |combo| @callbacks[combo].each do |callback| callback.call([previous_state, @state], *args, &block) end end previous_state else false end end |
#transition_to!(other_state) ⇒ String
Same as #transition_to, but raises an error if the transition is not allowed.
176 177 178 179 180 181 182 |
# File 'lib/nanomachine.rb', line 176 def transition_to!(other_state) if previous_state = transition_to(other_state) previous_state else raise InvalidTransitionError, "cannot transition from #{state.inspect} to #{other_state.inspect}" end end |