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