Class: SimpleMachine::SimpleMachinePrototype

Inherits:
Object
  • Object
show all
Defined in:
lib/simple_machine.rb

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(owner) ⇒ SimpleMachinePrototype

Returns a new instance of SimpleMachinePrototype.



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

def initialize(owner)
  @owner = owner
end

Class Attribute Details

.all_statesObject (readonly)

Returns the value of attribute all_states.



25
26
27
# File 'lib/simple_machine.rb', line 25

def all_states
  @all_states
end

.defined_transitionsObject (readonly)

Returns the value of attribute defined_transitions.



25
26
27
# File 'lib/simple_machine.rb', line 25

def defined_transitions
  @defined_transitions
end

.owner_class=(value) ⇒ Object (writeonly)

Sets the attribute owner_class

Parameters:

  • value

    the value to set the attribute owner_class to.



26
27
28
# File 'lib/simple_machine.rb', line 26

def owner_class=(value)
  @owner_class = value
end

.parents_state_field_nameObject

Returns the value of attribute parents_state_field_name.



24
25
26
# File 'lib/simple_machine.rb', line 24

def parents_state_field_name
  @parents_state_field_name
end

Class Method Details

.after_transition(&block) ⇒ Object



41
42
43
# File 'lib/simple_machine.rb', line 41

def after_transition(&block)
  @after_transition = block
end

.allow_transition(transition, options, &block) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/simple_machine.rb', line 44

def allow_transition(transition, options, &block)
  @defined_transitions ||= {}
  raise "Unknown source state #{options[:from]}. Please define it first as initial_state or in other_states." unless all_states.include?(options[:from])
  raise "Unknown target state #{options[:to]}. Please define it first as initial_state or in other_states." unless all_states.include?(options[:to])
  raise "Already defined transition '#{transition}' from '#{options[:from]}' state" if defined_transition?(transition, options[:from])
  
  @defined_transitions[options[:from]] = [] unless @defined_transitions.has_key?(options[:from])
  @defined_transitions[options[:from]] << { :transition => transition, :target_state => options[:to] }     
  
  transition_block = block_given? ? block : false
  
  class_eval do
    define_method "can_#{transition}?" do
      allowed_transitions.include? transition
    end
    define_method transition do
      current_state = @owner.send self.class.parents_state_field_name
      if self.class.defined_transitions[current_state].inject(false) { |memo, hash| memo or hash[:transition] == transition }
        raise "Unable to #{transition.to_s.gsub '_', ' '} due to guard"
      else
        raise "Invalid transition ##{transition.to_s.gsub '_', ' '} from '#{current_state}' state"
      end unless allowed_transitions.include? transition
      
      if !transition_block or @owner.instance_eval( &transition_block )
        variable = "@#{self.class.parents_state_field_name}"
        result = @owner.instance_eval { instance_variable_set variable, options[:to] }
        # after_transition callback
        after_transition_block = self.class.instance_eval { @after_transition }
        @owner.instance_eval &after_transition_block if after_transition_block
        result
      else
        false
      end
    end
  end   
end

.defined_transition?(transition, from_state) ⇒ Boolean

Returns:

  • (Boolean)


36
37
38
39
40
# File 'lib/simple_machine.rb', line 36

def defined_transition?(transition, from_state)
  return false unless @defined_transitions.has_key? from_state
  result = @defined_transitions[from_state].inject(false) { |sum, hash| sum || hash[:transition] == transition }
  return result
end

.initial_state(state) ⇒ Object



28
29
30
31
32
# File 'lib/simple_machine.rb', line 28

def initial_state(state)
  @all_states = [] << state
  variable = "@#{@parents_state_field_name}_default_state"
  @owner_class.instance_eval { instance_variable_set(variable, state) }
end

.other_states(*other_states) ⇒ Object



33
34
35
# File 'lib/simple_machine.rb', line 33

def other_states(*other_states)
  @all_states = @all_states | other_states
end

Instance Method Details

#all_statesObject



11
12
13
# File 'lib/simple_machine.rb', line 11

def all_states
  self.class.all_states
end

#allowed_transitionsObject



14
15
16
17
18
19
20
21
# File 'lib/simple_machine.rb', line 14

def allowed_transitions
  current_state = @owner.send self.class.parents_state_field_name
  result = self.class.defined_transitions[current_state].collect { |hash| hash[:transition] }
  result.collect do |transition|
    guard_method = "guard_for_#{transition}_on_#{self.class.parents_state_field_name}".to_sym
    transition if !@owner.respond_to?( guard_method ) or @owner.send(guard_method)
  end.compact
end