Module: Celluloid::FSM
- Defined in:
- lib/celluloid/fsm.rb
Overview
Simple finite state machines with integrated Celluloid timeout support Inspired by Erlang’s gen_fsm (www.erlang.org/doc/man/gen_fsm.html)
Basic usage:
class MyMachine
include Celluloid::FSM # NOTE: this does NOT pull in the Celluloid module
end
Inside an actor:
#
machine = MyMachine.new(current_actor)
Defined Under Namespace
Modules: ClassMethods Classes: State, UnattachedError
Constant Summary collapse
- DEFAULT_STATE =
Default state name unless one is explicitly set
:default
Instance Attribute Summary collapse
-
#actor ⇒ Object
readonly
Returns the value of attribute actor.
-
#state ⇒ Object
readonly
Obtain the current state of the FSM.
Class Method Summary collapse
-
.included(klass) ⇒ Object
Included hook to extend class methods.
Instance Method Summary collapse
-
#attach(actor) ⇒ Object
(also: #actor=)
Attach this FSM to an actor.
-
#initialize(actor = nil) ⇒ Object
Be kind and call super if you must redefine initialize.
-
#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.
Instance Attribute Details
#actor ⇒ Object (readonly)
Returns the value of attribute actor.
60 61 62 |
# File 'lib/celluloid/fsm.rb', line 60 def actor @actor end |
#state ⇒ Object (readonly)
Obtain the current state of the FSM
70 71 72 |
# File 'lib/celluloid/fsm.rb', line 70 def state @state end |
Class Method Details
.included(klass) ⇒ Object
Included hook to extend class methods
21 22 23 |
# File 'lib/celluloid/fsm.rb', line 21 def self.included(klass) klass.send :extend, ClassMethods end |
Instance Method Details
#attach(actor) ⇒ Object Also known as: actor=
Attach this FSM to an actor. This allows FSMs to wait for and initiate events in the context of a particular actor
74 75 76 |
# File 'lib/celluloid/fsm.rb', line 74 def attach(actor) @actor = actor end |
#initialize(actor = nil) ⇒ Object
Be kind and call super if you must redefine initialize
63 64 65 66 67 |
# File 'lib/celluloid/fsm.rb', line 63 def initialize(actor = nil) @state = self.class.default_state @actor = actor @actor ||= Celluloid.current_actor if Celluloid.actor? 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
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 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/celluloid/fsm.rb', line 86 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] unless new_state return if state_name == self.class.default_state raise ArgumentError, "invalid state for #{self.class}: #{state_name}" end if [:delay] raise UnattachedError, "can't delay unless attached" unless @actor @delayed_transition.cancel if @delayed_transition @delayed_transition = @actor.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) end |
#transition!(state_name) ⇒ Object
Immediate state transition with no sanity checks. “Dangerous!”
126 127 128 |
# File 'lib/celluloid/fsm.rb', line 126 def transition!(state_name) @state = state_name end |