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

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#actorObject (readonly)

Returns the value of attribute actor.



60
61
62
# File 'lib/celluloid/fsm.rb', line 60

def actor
  @actor
end

#stateObject (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, options = {})
  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 options[:delay]
    raise UnattachedError, "can't delay unless attached" unless @actor
    @delayed_transition.cancel if @delayed_transition

    @delayed_transition = @actor.after(options[: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