Module: Celluloid::FSM
- Defined in:
- lib/vendor/celluloid/lib/celluloid/fsm.rb
Overview
Turn concurrent objects into finite state machines Inspired by Erlang’s gen_fsm. See www.erlang.org/doc/man/gen_fsm.html
Defined Under Namespace
Modules: ClassMethods Classes: State
Constant Summary collapse
- DEFAULT_STATE =
Default state name unless one is explicitly set
:default
Class Method Summary collapse
-
.included(klass) ⇒ Object
Included hook to extend class methods.
Instance Method Summary collapse
-
#current_state ⇒ Object
(also: #state)
Obtain the current state of the FSM.
-
#transition(state_name, options = {}) ⇒ Object
Transition to another state Options: * delay: don’t transition immediately, wait the given number of seconds.
-
#transition!(state_name) ⇒ Object
Immediate state transition with no sanity checks.
Class Method Details
.included(klass) ⇒ Object
Included hook to extend class methods
8 9 10 11 |
# File 'lib/vendor/celluloid/lib/celluloid/fsm.rb', line 8 def self.included(klass) klass.send :include, Celluloid klass.send :extend, ClassMethods end |
Instance Method Details
#current_state ⇒ Object Also known as: state
Obtain the current state of the FSM
61 62 63 |
# File 'lib/vendor/celluloid/lib/celluloid/fsm.rb', line 61 def current_state defined?(@state) ? @state : @state = self.class.default_state end |
#transition(state_name, options = {}) ⇒ Object
Transition to another state Options:
-
delay: don’t transition immediately, wait the given number of seconds.
This will return a Celluloid::Timer object you can use to cancel the pending state transition.
Note: making additional state transitions will cancel delayed transitions
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/vendor/celluloid/lib/celluloid/fsm.rb', line 73 def transition(state_name, = {}) state_name = state_name.to_sym current_state = self.class.states[@state] return if current_state && current_state.name == state_name if current_state and not current_state.valid_transition? state_name valid = current_state.transitions.map(&:to_s).join(", ") raise ArgumentError, "#{self.class} can't change state from '#{@state}' to '#{state_name}', only to: #{valid}" end new_state = self.class.states[state_name] if !new_state and state_name == self.class.default_state # FIXME This probably isn't thread safe... or wise new_state = self.class.states[state_name] = State.new(state_name) end if new_state if [:delay] @delayed_transition.cancel if @delayed_transition @delayed_transition = after([:delay]) do transition! new_state.name new_state.call(self) end return @delayed_transition end if defined?(@delayed_transition) and @delayed_transition @delayed_transition.cancel @delayed_transition = nil end transition! new_state.name new_state.call(self) else raise ArgumentError, "invalid state for #{self.class}: #{state_name}" end end |
#transition!(state_name) ⇒ Object
Immediate state transition with no sanity checks. “Dangerous!”
116 117 118 |
# File 'lib/vendor/celluloid/lib/celluloid/fsm.rb', line 116 def transition!(state_name) @state = state_name end |