Skip to content

Commit

Permalink
Add PluginAWeek::StateMachine::Machine#states
Browse files Browse the repository at this point in the history
Add PluginAWeek::StateMachine::Event#transitions
  • Loading branch information
obrie committed Jul 3, 2008
1 parent b90d731 commit 26d60af
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 2 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.rdoc
@@ -1,5 +1,7 @@
== master == master


* Add PluginAWeek::StateMachine::Machine#states
* Add PluginAWeek::StateMachine::Event#transitions
* Allow creating transitions with no from state (effectively allowing the transition for *any* from state) * Allow creating transitions with no from state (effectively allowing the transition for *any* from state)
* Reduce the number of objects created for each transition * Reduce the number of objects created for each transition


Expand Down
5 changes: 5 additions & 0 deletions lib/state_machine/event.rb
Expand Up @@ -11,6 +11,9 @@ class Event
# The name of the action that fires the event # The name of the action that fires the event
attr_reader :name attr_reader :name


# The list of transitions that can be made for this event
attr_reader :transitions

delegate :owner_class, delegate :owner_class,
:to => :machine :to => :machine


Expand All @@ -21,6 +24,7 @@ def initialize(machine, name, options = {})
@machine = machine @machine = machine
@name = name @name = name
@options = options.stringify_keys @options = options.stringify_keys
@transitions = []


add_transition_actions add_transition_actions
add_transition_callbacks add_transition_callbacks
Expand Down Expand Up @@ -63,6 +67,7 @@ def transition(options = {})
callback = Proc.new {|record, *args| try_transition(transition, true, record, *args)} callback = Proc.new {|record, *args| try_transition(transition, true, record, *args)}
owner_class.send("transition_bang_on_#{name}", callback, options) owner_class.send("transition_bang_on_#{name}", callback, options)


transitions << transition
transition transition
end end


Expand Down
10 changes: 10 additions & 0 deletions lib/state_machine/machine.rb
Expand Up @@ -15,6 +15,9 @@ class Machine
# The events that trigger transitions # The events that trigger transitions
attr_reader :events attr_reader :events


# A list of the states defined in the transitions of all of the events
attr_reader :states

# The attribute for which the state machine is being defined # The attribute for which the state machine is being defined
attr_accessor :attribute attr_accessor :attribute


Expand Down Expand Up @@ -44,6 +47,7 @@ def initialize(owner_class, attribute, options = {})
@attribute = attribute.to_s @attribute = attribute.to_s
@initial_state = options[:initial] @initial_state = options[:initial]
@events = {} @events = {}
@states = []


add_named_scopes add_named_scopes
end end
Expand Down Expand Up @@ -110,6 +114,12 @@ def event(name, options = {}, &block)
name = name.to_s name = name.to_s
event = events[name] = Event.new(self, name, options) event = events[name] = Event.new(self, name, options)
event.instance_eval(&block) event.instance_eval(&block)

# Record the states
event.transitions.each do |transition|
@states |= ([transition.to_state] + transition.from_states)
end

event event
end end


Expand Down
9 changes: 9 additions & 0 deletions test/unit/event_test.rb
Expand Up @@ -14,6 +14,10 @@ def test_should_have_a_name
assert_equal 'turn_on', @event.name assert_equal 'turn_on', @event.name
end end


def test_should_not_have_any_transitions
assert @event.transitions.empty?
end

def test_should_define_an_event_action_on_the_owner_class def test_should_define_an_event_action_on_the_owner_class
switch = new_switch switch = new_switch
assert switch.respond_to?(:turn_on) assert switch.respond_to?(:turn_on)
Expand Down Expand Up @@ -81,6 +85,11 @@ def test_should_allow_transitioning_from_multiple_states
assert @event.transition(:to => 'on', :from => %w(off on)) assert @event.transition(:to => 'on', :from => %w(off on))
end end


def test_should_have_transitions
@event.transition(:to => 'on')
assert @event.transitions.any?
end

def teardown def teardown
Switch.class_eval do Switch.class_eval do
@transition_on_turn_on_callbacks = nil @transition_on_turn_on_callbacks = nil
Expand Down
26 changes: 24 additions & 2 deletions test/unit/machine_test.rb
Expand Up @@ -20,6 +20,10 @@ def test_should_have_an_owner_class
def test_should_not_have_any_events def test_should_not_have_any_events
assert @machine.events.empty? assert @machine.events.empty?
end end

def test_should_not_have_any_states
assert @machine.states.empty?
end
end end


class MachineWithInvalidOptionsTest < Test::Unit::TestCase class MachineWithInvalidOptionsTest < Test::Unit::TestCase
Expand Down Expand Up @@ -121,9 +125,27 @@ def test_should_evaluate_block_within_event_context
assert responded assert responded
end end


def test_should_store_the_event def test_should_have_events
@machine.event(:turn_on) {} @machine.event(:turn_on) {}
assert_equal 1, @machine.events.size assert_equal %w(turn_on), @machine.events.keys
end
end

class MachineWithEventsAndTransitionsTest < Test::Unit::TestCase
def setup
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state')
@machine.event(:turn_on) do
transition :to => 'on', :from => 'off'
transition :to => 'error', :from => 'unknown'
end
end

def test_should_have_events
assert_equal %w(turn_on), @machine.events.keys
end

def test_should_have_states
assert_equal %w(on off error unknown), @machine.states
end end
end end


Expand Down

0 comments on commit 26d60af

Please sign in to comment.