Module: DataMapper::Is::StateMachine::EventDsl

Defined in:
lib/dm-is-state_machine/is/dsl/event_dsl.rb

Overview

Event DSL (Domain Specific Language)

Instance Method Summary collapse

Instance Method Details

#event(name, &block) ⇒ Object

Define an event. This takes a block which describes all valid transitions for this event.

Example:

class TrafficLight
  include DataMapper::Resource
  property :id, Serial
  is :state_machine, :initial => :green, :column => :color do
    # state definitions go here...

    event :forward do
      transition :from => :green,  :to => :yellow
      transition :from => :yellow, :to => :red
      transition :from => :red,    :to => :green
    end
  end
end

transition takes a hash where :to is the state to transition to and :from is a state (or Array of states) from which this event can be fired.



29
30
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
# File 'lib/dm-is-state_machine/is/dsl/event_dsl.rb', line 29

def event(name, &block)
  unless state_machine_context?(:is)
    raise InvalidContext, "Valid only in 'is :state_machine' block"
  end

  # ===== Setup context =====
  machine = @is_state_machine[:machine]
  event = Data::Event.new(name, machine)
  machine.events << event
  @is_state_machine[:event] = {
    :name   => name,
    :object => event
  }
  push_state_machine_context(:event)

  # ===== Define methods =====
  define_method("#{name}!") do
    transition!(name)
  end

  # Possible alternative to the above:
  # (class_eval is typically faster than define_method)
  #
  # self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
  #   def #{name}!
  #     machine.current_state_name = __send__(:"#{column}")
  #     machine.fire_event(name, self)
  #     __send__(:"#{column}="), machine.current_state_name
  #   end
  # RUBY

  yield if block_given?

  # ===== Teardown context =====
  pop_state_machine_context
end

#transition(options) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
# File 'lib/dm-is-state_machine/is/dsl/event_dsl.rb', line 66

def transition(options)
  unless state_machine_context?(:event)
    raise InvalidContext, "Valid only in 'event' block"
  end
  event_name   = @is_state_machine[:event][:name]
  event_object = @is_state_machine[:event][:object]

  from = options[:from]
  to   = options[:to]
  event_object.add_transition(from, to)
end