lib/state_fu/lathe.rb in davidlee-state-fu-0.2.0 vs lib/state_fu/lathe.rb in davidlee-state-fu-0.3.1
- old
+ new
@@ -1,12 +1,19 @@
module StateFu
+ # A Lathe parses and a Machine definition and returns a freshly turned
+ # Machine.
+ #
+ # It provides the means to define the arrangement of StateFu objects
+ # ( eg States and Events) which comprise a workflow, process,
+ # lifecycle, circuit, syntax, etc.
class Lathe
# NOTE: Sprocket is the abstract superclass of Event and State
attr_reader :machine, :sprocket, :options
+ # you don't need to call this directly.
def initialize( machine, sprocket = nil, options={}, &block )
@machine = machine
@sprocket = sprocket
@options = options.symbolize_keys!
@@ -139,11 +146,11 @@
options.symbolize_keys!
require_sprocket( StateFu::State, NilClass )
if child? && sprocket.is_a?( StateFu::State ) # in state block
targets = options.delete(:to)
evt = define_event( name, options, &block )
- evt.from sprocket unless evt.origins
+ evt.from sprocket unless sprocket.nil?
evt.to( targets ) unless targets.nil?
evt
else # in master lathe
origins = options.delete( :from )
targets = options.delete( :to )
@@ -224,27 +231,56 @@
require_sprocket( StateFu::Event )
sprocket.to( *args, &block )
end
#
+ # define chained events and states succinctly
+ # usage: chain 'state1 -event1-> state2 -event2-> state3'
+ def chain (string)
+ rx_word = /([a-zA-Z0-9_]+)/
+ rx_state = /^#{rx_word}$/
+ rx_event = /^-#{rx_word}->$/
+ previous = nil
+ string.split.each do |chunk|
+ case chunk
+ when rx_state
+ current = state($1)
+ if previous.is_a?( StateFu::Event )
+ previous.to( current )
+ end
+ when rx_event
+ current = event($1)
+ if previous.is_a?( StateFu::State )
+ current.from( previous )
+ end
+ else
+ raise ArgumentError, "'#{chunk}' is not a valid token"
+ end
+ previous = current
+ end
+ end
+
+ #
# do something with all states / events
#
def each_sprocket( type, *args, &block)
- require_no_sprocket()
+
options = args.extract_options!.symbolize_keys!
if args == [:ALL] || args == []
args = machine.send("#{type}s").except( options.delete(:except) )
end
args.map { |name| self.send( type, name, options.dup, &block) }.extend StateArray
end
def states( *args, &block )
+ require_no_sprocket()
each_sprocket( 'state', *args, &block )
end
alias_method :all_states, :states
alias_method :each_state, :states
def events( *args, &block )
+ require_sprocket( NilClass, StateFu::State )
each_sprocket( 'event', *args, &block )
end
alias_method :all_events, :events
alias_method :each_event, :events