Class: MetaState::Machine

Inherits:
Object
  • Object
show all
Defined in:
lib/meta-state.rb

Direct Known Subclasses

SockJS::Session

Constant Summary collapse

NON_MESSAGES =
[:on_exit, :on_enter]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeMachine

Returns a new instance of Machine.



97
98
99
100
# File 'lib/meta-state.rb', line 97

def initialize
  @debug_block = nil
  assign_state(self.class.default_state)
end

Instance Attribute Details

#current_stateObject (readonly)

Returns the value of attribute current_state.



96
97
98
# File 'lib/meta-state.rb', line 96

def current_state
  @current_state
end

Class Method Details

.add_state(state) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
# File 'lib/meta-state.rb', line 10

def add_state(state)
  @default_state ||= state
  states
  @states[state] = true
  name = state.name.sub(/.*::/,'').downcase
  state_names
  @state_names[name] = state
  @state_names[name.to_sym] = state
  include state
  @void_state_module = nil
end

.build_void_stateObject



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/meta-state.rb', line 64

def build_void_state
  methods = (self.states.keys.map do |state|
    state.instance_methods
  end.flatten + NON_MESSAGES).uniq

  @void_state_module = Module.new do
    methods.each do |method|
      if NON_MESSAGES.include?(method)
        define_method(method){|*args| }
      else
        define_method(method) do |*args|
          raise WrongStateError, "Message #{method} received in state #{current_state}"
        end
      end
    end
  end

  include @void_state_module
end

.default_stateObject



28
29
30
# File 'lib/meta-state.rb', line 28

def default_state
  @default_state || superclass.default_state
end

.default_state=(state) ⇒ Object

Explicitly set the default (i.e. initial state) for an FSM Normally, this defaults to the first state defined, but some folks like to be explicit



42
43
44
# File 'lib/meta-state.rb', line 42

def default_state=(state)
  @default_state = state
end

.state(name, &block) ⇒ Object



22
23
24
25
26
# File 'lib/meta-state.rb', line 22

def state(name, &block)
  mod = Module.new(&block)
  const_set(name, mod)
  add_state(mod)
end

.state_namesObject



46
47
48
49
50
51
52
53
# File 'lib/meta-state.rb', line 46

def state_names
  @state_names ||= {}
  if Machine > superclass
    superclass.state_names.merge(@state_names)
  else
    @state_names
  end
end

.statesObject



55
56
57
58
59
60
61
62
# File 'lib/meta-state.rb', line 55

def states
  @states ||= {}
  if Machine > superclass
    superclass.states.merge(@states)
  else
    @states
  end
end

.void_state_moduleObject



32
33
34
35
36
37
# File 'lib/meta-state.rb', line 32

def void_state_module
  if @void_state_module.nil?
    build_void_state
  end
  @void_state_module
end

Instance Method Details

#debug_with(&block) ⇒ Object



92
93
94
# File 'lib/meta-state.rb', line 92

def debug_with(&block)
  @debug_block = block
end

#state=(state) ⇒ Object

Explicitly put an FSM into a particular state. Simultaneously enters a state of sin. Use sparingly if at all.



87
88
89
90
# File 'lib/meta-state.rb', line 87

def state=(state)
  mod = state_module(state)
  assign_state(mod)
end