Class: FSM::Machine
- Inherits:
-
Object
- Object
- FSM::Machine
- Defined in:
- lib/fsm/machine.rb
Instance Attribute Summary collapse
-
#current_state_attribute_name ⇒ Object
Returns the value of attribute current_state_attribute_name.
-
#initial_state_name ⇒ Object
Returns the value of attribute initial_state_name.
-
#states ⇒ Object
Returns the value of attribute states.
-
#transitions ⇒ Object
Returns the value of attribute transitions.
Class Method Summary collapse
- .[](includer) ⇒ Object
- .[]=(*args) ⇒ Object
- .get_current_state_name(target) ⇒ Object
- .set_current_state_name(target, value) ⇒ Object
Instance Method Summary collapse
- #available_transitions(target) ⇒ Object
- #build_transition_methods ⇒ Object
- #draw_graph(options = {}) ⇒ Object
-
#initialize(target_class) ⇒ Machine
constructor
A new instance of Machine.
- #reachable_states(target) ⇒ Object
- #state(name, options = {}) ⇒ Object
-
#state_for_name(name, quiet = false) ⇒ Object
Lookup a State by it’s name raises ArgumentError if state can not be found unless quiet is set to true.
-
#to_dot(options = {}) ⇒ Object
Convert this state machine to the dot format of graphviz.
- #transition(name, from_name, to_name, options = {}) ⇒ Object
Constructor Details
#initialize(target_class) ⇒ Machine
Returns a new instance of Machine.
5 6 7 8 9 10 |
# File 'lib/fsm/machine.rb', line 5 def initialize(target_class) @target_class = target_class self.states = [] self.transitions = [] self.current_state_attribute_name = :state end |
Instance Attribute Details
#current_state_attribute_name ⇒ Object
Returns the value of attribute current_state_attribute_name.
3 4 5 |
# File 'lib/fsm/machine.rb', line 3 def current_state_attribute_name @current_state_attribute_name end |
#initial_state_name ⇒ Object
Returns the value of attribute initial_state_name.
3 4 5 |
# File 'lib/fsm/machine.rb', line 3 def initial_state_name @initial_state_name end |
#states ⇒ Object
Returns the value of attribute states.
3 4 5 |
# File 'lib/fsm/machine.rb', line 3 def states @states end |
#transitions ⇒ Object
Returns the value of attribute transitions.
3 4 5 |
# File 'lib/fsm/machine.rb', line 3 def transitions @transitions end |
Class Method Details
.[](includer) ⇒ Object
12 13 14 |
# File 'lib/fsm/machine.rb', line 12 def self.[](includer) (@machines ||= {})[includer] end |
.[]=(*args) ⇒ Object
16 17 18 |
# File 'lib/fsm/machine.rb', line 16 def self.[]=(*args) (@machines ||= {})[args.first] = args.last end |
.get_current_state_name(target) ⇒ Object
41 42 43 |
# File 'lib/fsm/machine.rb', line 41 def self.get_current_state_name(target) target.send(Machine[target.class].current_state_attribute_name) || self.initial_state_name end |
.set_current_state_name(target, value) ⇒ Object
45 46 47 48 |
# File 'lib/fsm/machine.rb', line 45 def self.set_current_state_name(target, value) value = value && value.is_a?(Symbol) ? value.to_s : value target.send("#{Machine[target.class].current_state_attribute_name}=", value) end |
Instance Method Details
#available_transitions(target) ⇒ Object
60 61 62 63 64 |
# File 'lib/fsm/machine.rb', line 60 def available_transitions(target) current_state_name = Machine.get_current_state_name(target) state = state_for_name(current_state_name) state.transitions.values end |
#build_transition_methods ⇒ Object
67 68 69 70 71 72 |
# File 'lib/fsm/machine.rb', line 67 def build_transition_methods names = self.transitions.map() {|transition| transition.name}.uniq names.each do |name| define_transition_method(name) end end |
#draw_graph(options = {}) ⇒ Object
94 95 96 97 98 99 100 101 102 103 |
# File 'lib/fsm/machine.rb', line 94 def draw_graph( = {}) format = [:format] || :png extension = [:extension] || format file_name = [:outfile] || "#{@target_class.name.downcase}.#{extension}" cmd = "dot -T#{format} -o#{file_name}" IO.popen cmd, 'w' do |io| io.write to_dot end raise 'dot failed' unless $?.success? end |
#reachable_states(target) ⇒ Object
51 52 53 54 55 56 57 58 |
# File 'lib/fsm/machine.rb', line 51 def reachable_states(target) reachables = [] current_state_name = Machine.get_current_state_name(target) self.states.map do |state| reachables += state.to_states if state.name == current_state_name end reachables end |
#state(name, options = {}) ⇒ Object
20 21 22 23 24 |
# File 'lib/fsm/machine.rb', line 20 def state(name, = {}) raise "State is already defined: '#{name}'" if self.state_for_name(name, true) self.states << State.new(name, @target_class, ) self.initial_state_name=(name) unless self.initial_state_name end |
#state_for_name(name, quiet = false) ⇒ Object
Lookup a State by it’s name raises ArgumentError if state can not be found unless quiet is set to true
76 77 78 79 80 |
# File 'lib/fsm/machine.rb', line 76 def state_for_name(name, quiet = false) state = self.states.detect() {|state| state.name == name} raise ArgumentError.new("Unknonw state '#{name}'") unless quiet || state state end |
#to_dot(options = {}) ⇒ Object
Convert this state machine to the dot format of graphviz
83 84 85 86 87 88 89 90 91 |
# File 'lib/fsm/machine.rb', line 83 def to_dot( = {}) s = self.states.map do |state| " #{state.to_dot(options)};" end t = self.transitions.map do |transition| " #{transition.to_dot(options)};" end "digraph FSM_#{@target_class.name} {\n#{s.join("\n")}\n\n#{t.join("\n")}\n}" end |
#transition(name, from_name, to_name, options = {}) ⇒ Object
31 32 33 34 35 36 37 38 39 |
# File 'lib/fsm/machine.rb', line 31 def transition(name, from_name, to_name, = {}) raise ArgumentError.new("name, from_name and to_name are required") if name.nil? || from_name.nil? || to_name.nil? from_state = self.state_for_name(from_name) to_state = self.state_for_name(to_name) transition = Transition.new(name, from_state, to_state, ) from_state.add_transition(transition) self.transitions << transition end |