Permalink
Browse files

Stateflow gem version 0.0.1

No tests yet
No readme
  • Loading branch information...
1 parent 58720b8 commit 83c575ce6cca853c45af838be7a7584578973540 Ryan Oberholzer committed Mar 22, 2010
Showing with 84 additions and 2 deletions.
  1. +3 −0 .gitignore
  2. +48 −0 examples/test.rb
  3. +3 −1 lib/stateflow/event.rb
  4. +30 −1 lib/stateflow/transition.rb
View
@@ -0,0 +1,3 @@
+pkg
+doc
+Manifest
View
@@ -0,0 +1,48 @@
+require 'rubygems'
+require 'stateflow'
+
+class Test
+ include Stateflow
+
+ stateflow do
+
+ initial :love
+
+ state :love do
+ enter lambda { |t| p "Entering love" }
+ exit :exit_love
+ end
+
+ state :hate do
+ enter lambda { |t| p "Entering hate" }
+ exit lambda { |t| p "Exiting hate" }
+ end
+
+ state :mixed do
+ enter lambda { |t| p "Entering mixed" }
+ exit lambda { |t| p "Exiting mixed" }
+ end
+
+ event :b do
+ transitions :from => :love, :to => :hate, :if => :no_ice_cream
+ transitions :from => :hate, :to => :love
+ end
+
+ event :a do
+ transitions :from => :love, :to => [:hate, :mixed], :decide => :likes_ice_cream?
+ transitions :from => [:hate, :mixed], :to => :love
+ end
+ end
+
+ def likes_ice_cream?
+ rand(10) > 5 ? :mixed : :hate
+ end
+
+ def exit_love
+ p "Exiting love"
+ end
+
+ def no_ice_cream
+ rand(4) > 2 ? true : false
+ end
+end
@@ -16,7 +16,9 @@ def fire(current_state, klass)
transition = @transitions.select{ |t| t.from.include? current_state.name }.first
raise NoTransitionFound.new("No transition found for event #{@name}") if transition.nil?
- new_state = klass.machine.states[transition.to]
+ return false unless transition.can_transition?(klass)
+
+ new_state = klass.machine.states[transition.find_to_state(klass)]
raise NoStateFound.new("Invalid state #{transition.to.to_s} for transition.") if new_state.nil?
current_state.execute_action(:exit, klass)
@@ -1,9 +1,38 @@
module Stateflow
+ class IncorrectTransition < Exception; end
+
class Transition
- attr_accessor :from, :to
+ attr_reader :from, :to, :if, :decide
+
def initialize(args)
@from = [args[:from]].flatten
@to = args[:to]
+ @if = args[:if]
+ @decide = args[:decide]
end
+
+ def can_transition?(base)
+ return true unless @if
+ execute_action(@if, base)
+ end
+
+ def find_to_state(base)
+ raise IncorrectTransition.new("Array of destinations and no decision") if @to.is_a?(Array) && @decide.nil?
+ return @to unless @to.is_a?(Array)
+
+ to = execute_action(@decide, base)
+
+ @to.include?(to) ? to : (raise NoStateFound.new("Decision did not return a state that was set in the 'to' argument"))
+ end
+
+ private
+ def execute_action(action, base)
+ case action
+ when Symbol, String
+ base.send(action)
+ when Proc
+ action.call(base)
+ end
+ end
end
end

0 comments on commit 83c575c

Please sign in to comment.