Class: StatefulEnum::Machine::Event

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

Direct Known Subclasses

Graph::EventDrawer, PlantUML::EventStore

Instance Method Summary collapse

Constructor Details

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

Returns a new instance of Event.



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
77
78
# File 'lib/stateful_enum/machine.rb', line 33

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[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.key? send(column).to_sym
    end

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

Instance Method Details

#after(&block) ⇒ Object



106
107
108
# File 'lib/stateful_enum/machine.rb', line 106

def after(&block)
  @after = block
end

#allObject



98
99
100
# File 'lib/stateful_enum/machine.rb', line 98

def all
  @states
end

#before(&block) ⇒ Object



102
103
104
# File 'lib/stateful_enum/machine.rb', line 102

def before(&block)
  @before = block
end

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



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

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