Class: StatefulEnum::Machine::Event

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

Direct Known Subclasses

Graph::EventDrawer

Instance Method Summary collapse

Constructor Details

#initialize(model, column, states, prefix, suffix, name, &block) ⇒ Event

Returns a new instance of Event.



31
32
33
34
35
36
37
38
39
40
41
42
43
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
# File 'lib/stateful_enum/machine.rb', line 31

def initialize(model, column, states, prefix, suffix, name, &block)
  @states, @name, @transitions, @before, @after = states, name, {}, nil, nil

  instance_eval(&block) if block

  transitions, before, after = @transitions, @before, @after
  new_method_name = "#{prefix}#{name}#{suffix}"

  # defining event methods
  model.class_eval do
    # def assign()
    detect_enum_conflict! column, new_method_name
    define_method new_method_name do
      to, condition = transitions[self.send(column).to_sym]
      #TODO better error
      if to && (!condition || instance_exec(&condition))
        #TODO transaction?
        instance_eval(&before) if before
        original_method = self.class.send(:_enum_methods_module).instance_method "#{prefix}#{to}#{suffix}!"
        ret = original_method.bind(self).call
        instance_eval(&after) if after
        ret
      else
        false
      end
    end

    # def assign!()
    detect_enum_conflict! column, "#{new_method_name}!"
    define_method "#{new_method_name}!" do
      send(new_method_name) || raise('Invalid transition')
    end

    # def can_assign?()
    detect_enum_conflict! column, "can_#{new_method_name}?"
    define_method "can_#{new_method_name}?" do
      transitions.has_key? self.send(column).to_sym
    end

    # def assign_transition()
    detect_enum_conflict! column, "#{new_method_name}_transition"
    define_method "#{new_method_name}_transition" do
      transitions[self.send(column).to_sym].try! :first
    end
  end
end

Instance Method Details

#after(&block) ⇒ Object



104
105
106
# File 'lib/stateful_enum/machine.rb', line 104

def after(&block)
  @after = block
end

#allObject



96
97
98
# File 'lib/stateful_enum/machine.rb', line 96

def all
  @states
end

#before(&block) ⇒ Object



100
101
102
# File 'lib/stateful_enum/machine.rb', line 100

def before(&block)
  @before = block
end

#transition(transitions, options = {}) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/stateful_enum/machine.rb', line 78

def transition(transitions, options = {})
  if options.blank?
    options[:if] = transitions.delete :if
    #TODO should err if if & unless were specified together?
    if (unless_condition = transitions.delete :unless)
      options[:if] = -> { !instance_exec(&unless_condition) }
    end
  end
  transitions.each_pair do |from, to|
    raise "Undefined state #{to}" unless @states.include? to
    Array(from).each do |f|
      raise "Undefined state #{f}" unless @states.include? f
      raise "Duplicate entry: Transition from #{f} to #{@transitions[f].first} has already been defined." if @transitions[f]
      @transitions[f] = [to, options[:if]]
    end
  end
end