Class: Hifsm::State

Inherits:
Object
  • Object
show all
Includes:
Callbacks
Defined in:
lib/hifsm/state.rb

Constant Summary collapse

CALLBACKS =
[:before_enter, :before_exit, :after_enter, :after_exit, :action].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Callbacks

#set_callbacks, #trigger, #trigger?

Constructor Details

#initialize(name, parent = nil, options) ⇒ State

Returns a new instance of State.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/hifsm/state.rb', line 9

def initialize(name, parent = nil, options)
  @name = name.to_s
  @parent = parent
  CALLBACKS.each do |cb|
    set_callbacks cb, options[cb]
  end
  @transitions = Hash.new {|h, key| h[key] = Array.new }

  if options[:sub_states].empty?
    @sub_fsm = nil
  else
    @sub_fsm = Hifsm::FSM.new(nil, self)
    options[:sub_states].each {|args, block| @sub_fsm.state(*args, &block) }
    options[:sub_events].each {|args, block| @sub_fsm.event(*args, &block) }
  end
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



7
8
9
# File 'lib/hifsm/state.rb', line 7

def name
  @name
end

#sub_fsmObject (readonly)

Returns the value of attribute sub_fsm.



7
8
9
# File 'lib/hifsm/state.rb', line 7

def sub_fsm
  @sub_fsm
end

Instance Method Details

#act!(target, *args) ⇒ Object



26
27
28
29
# File 'lib/hifsm/state.rb', line 26

def act!(target, *args)
  @parent.act!(target, *args) if @parent
  trigger(:action, target, *args).last
end

#add_transition(ev) ⇒ Object



31
32
33
34
# File 'lib/hifsm/state.rb', line 31

def add_transition(ev)
  name = ev.name.to_s
  @transitions[name].push ev
end

#enter!Object



36
37
38
39
40
41
42
# File 'lib/hifsm/state.rb', line 36

def enter!
  if @sub_fsm
    @sub_fsm.initial_state!.enter!
  else
    self
  end
end

#eventsObject



44
45
46
# File 'lib/hifsm/state.rb', line 44

def events
  @transitions.keys + (@sub_fsm && @sub_fsm.all_events || [])
end

#fire(target, event_name, *args, &new_state_callback) ⇒ Object



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

def fire(target, event_name, *args, &new_state_callback)
  event_name = event_name.to_s
  @transitions[event_name].each do |ev|
    if ev.guard?(target, *args)
      from_state = self
      to_state = ev.to
      if ev.trigger?(:before, target, *args) &&
          to_state.trigger?(:before_enter, target, *args) &&
          from_state.trigger?(:before_exit, target, *args)
        new_state_callback.call(to_state.enter!)
        from_state.trigger(:after_exit, target, *args)
        to_state.trigger(:after_enter, target, *args)
        ev.trigger(:after, target, *args)
      end
      return target
    end
  end
  if @parent
    return @parent.fire(target, event_name, *args, &new_state_callback)
  end
  raise Hifsm::MissingTransition.new(to_s, event_name)
end

#get_substate!(name) ⇒ Object



48
49
50
51
# File 'lib/hifsm/state.rb', line 48

def get_substate!(name)
  raise Hifsm::MissingState.new(name.to_s) unless @sub_fsm
  @sub_fsm.get_state!(name)
end

#to_sObject



87
88
89
90
91
92
93
# File 'lib/hifsm/state.rb', line 87

def to_s
  if @parent
    "#{@parent.to_s}.#{@name}"
  else
    @name
  end
end

#valid_events(target, *args) ⇒ Object



53
54
55
56
57
58
59
60
61
62
# File 'lib/hifsm/state.rb', line 53

def valid_events(target, *args)
  own_events = events.find_all do |event_name|
    @transitions[event_name].any? {|event| event.guard?(target, *args)}
  end
  if @parent
    (own_events + @parent.valid_events(target, *args)).uniq
  else
    own_events.uniq
  end
end