lib/state_fu/binding.rb in davidlee-state-fu-0.10.0 vs lib/state_fu/binding.rb in davidlee-state-fu-0.11.0
- old
+ new
@@ -25,14 +25,14 @@
# define event methods on this binding and its @object
MethodFactory.new( self ).install!
@machine.helpers.inject_into( self )
end
- alias_method :o, :object
- alias_method :obj, :object
- alias_method :model, :object
- alias_method :instance, :object
+ alias_method :o, :object
+ alias_method :obj, :object
+ alias_method :model, :object
+ alias_method :instance, :object
alias_method :workflow, :machine
alias_method :state_machine, :machine
#
@@ -68,16 +68,10 @@
e.can_transition_from? current_state
end.extend EventArray
end
alias_method :events_from_current_state, :events
- # the subset of events() whose requirements for firing are NOT met
- # (with the arguments supplied, if any)
- def invalid_events( *args )
- ( events - valid_events( *args ) ).extend StateArray
- end
-
# all states which can be reached from the current_state.
# Does not check transition requirements, etc.
def next_states
events.map(&:targets).compact.flatten.uniq.extend StateArray
end
@@ -93,52 +87,30 @@
def valid_transitions(*args)
transitions.valid.with(*args)
end
def valid_next_states(*args)
- transitions.with(*args).targets
+ valid_transitions(*args).targets
end
def valid_events(*args)
- transitions.with(*args).events
+ valid_transitions(*args).events
end
+
+ def invalid_events(*args)
+ (events - valid_events(*args)).extend StateArray
+ end
+
# initializes a new Transition to the given destination, with the
# given *args (to be passed to requirements and hooks).
#
# If a block is given, it yields the Transition or is executed in
# its evaluation context, depending on the arity of the block.
def transition( event_or_array, *args, &block )
return transitions.with(*args, &block).find(event_or_array)
end
- alias_method :fire, :transition
- alias_method :fire_event, :transition
- alias_method :trigger, :transition
- alias_method :trigger_event, :transition
- alias_method :begin_transition, :transition
-
- # check that the event and target are valid (all requirements are
- # met) with the given (optional) arguments
- def fireable?( event_or_array, *args )
- begin
- return nil unless t = transition( event_or_array, *args )
- !! t.requirements_met?
- rescue InvalidTransition => e
- nil
- end
- end
-
- # construct an event transition and fire it, returning the transition.
- # (which is == true if the transition completed successfully.)
- def fire!( event_or_array, *args, &block)
- # TODO rather than die, try to find the next valid transition and fire that
- t = transition(event_or_array, *args, &block )
- t.fire!
- end
- alias_method :trigger!, :fire!
- alias_method :transition!, :fire!
-
#
# next_transition and friends: when there's exactly one valid move
#
# if there is exactly one legal & valid transition which can be fired with
@@ -153,32 +125,32 @@
end
# if there is exactly one state reachable via a transition which
# is valid with the given optional arguments, return it.
def next_state(*args, &block)
- transitions.with(*args, &block).next_state
+ transitions.with(*args, &block).next_state
end
# if there is exactly one event which is valid with the given
# optional arguments, return it
def next_event( *args )
transitions.with(*args, &block).next_event
end
# if there is a next_transition, create, fire & return it
- # otherwise raise an InvalidTransition
+ # otherwise raise an IllegalTransition
def next!( *args, &block )
if t = next_transition( *args, &block )
t.fire!
else
raise TransitionNotFound.new( self, valid_transitions(*args), "Exactly 1 valid transition required.")
end
end
alias_method :next_transition!, :next!
alias_method :next_event!, :next!
alias_method :next_state!, :next!
-
+
# if there is a next_transition, return true / false depending on
# whether its requirements are met
# otherwise, nil
def next?( *args, &block )
if t = next_transition( *args, &block )
@@ -200,17 +172,16 @@
transitions.cyclic.with(*args, &block).find(event_or_array)
end
end
# if there is a single possible cycle() transition, fire and return it
- # otherwise raise an InvalidTransition
+ # otherwise raise an IllegalTransition
def cycle!(event_or_array=nil, *args, &block )
- if t = cycle(event_or_array, *args, &block )
+ returning cycle(event_or_array, *args, &block ) do |t|
+ raise TransitionNotFound.new( self, transitions.cyclic.with(*args,&block), "Cannot cycle! unless there is exactly one cyclic event") \
+ if t.nil?
t.fire!
- t
- else
- raise TransitionNotFound.new( self, transitions.cyclic.with(*args,&block), "Cannot cycle! unless there is exactly one cyclic event")
end
end
# if there is one possible cyclical event, evaluate its
# requirements (true/false), else nil
@@ -231,17 +202,17 @@
persister.current_state=( machine.states[target] )
end
# display something sensible that doesn't take up the whole screen
def inspect
- '|<= ' + self.class.to_s + ' ' +
+ '<#' + self.class.to_s + ' ' +
attrs = [[:current_state, state_name.inspect],
[:object_type , @object.class],
[:method_name , method_name.inspect],
[:field_name , field_name.inspect],
- [:machine , machine.inspect]].
- map {|x| x.join('=') }.join( " " ) + ' =>|'
+ [:machine , machine.to_s]].
+ map {|x| x.join('=') }.join( " " ) + '>'
end
# let's be == (and hence ===) the current_state_name as a symbol.
# a nice little convenience.
def == other
@@ -265,34 +236,45 @@
end
persister.reload
self
end
- # This method is called from methods defined by MethodFactory.
- # You don't want to call it directly.
- def _event_method(action, event, *args)
- target_or_options = args.shift
- options = {}
- case target_or_options
- when Hash
- options = target_or_options.symbolize_keys!
- target = target_or_options.delete[:to]
- when Symbol, String
- target = target_or_options.to_sym
- when nil
- target = nil
- end
+ def inspect
+ s = self.to_s
+ s = s[0,s.length-1]
+ s << " object=#{object}"
+ s << " current_state=#{current_state.to_sym.inspect rescue nil}"
+ s << " events=#{events.map(&:to_sym).inspect rescue nil}"
+ s << " machine=#{machine.to_s}"
+ s << ">"
+ s
+ end
- case action
- when :get_transition
- transition [event, target], *args, &lambda {|t| t.options = options}
- when :query_transition
- fireable? [event, target], *args, &lambda {|t| t.options = options}
- when :fire_transition
- fire! [event, target], *args, &lambda {|t| t.options = options}
- else
- raise ArgumentError.new(action)
- end
+ # These methods are called from methods defined by MethodFactory.
+ # You probably don't want to call them directly.
+
+ # event_name
+ def find_transition(event, target=nil, *args)
+ target ||= args.last[:to].to_sym rescue nil
+ query = transitions.for_event(event).to(target).with(*args)
+ query.find || query.valid.singular || NilTransition.new
+ # transition = binding.transitions.with(*args).search([event, target])
+ end
+
+ # event_name?
+ def can_transition?(event, target=nil, *args)
+ begin
+ if t = find_transition(event, target, *args)
+ t.valid?(*args)
+ end
+ rescue IllegalTransition, UnknownTarget
+ nil
+ end
+ end
+
+ # event_name!
+ def fire_transition!(event, target=nil, *args)
+ find_transition(event, target, *args).fire!
end
#
# transition constructor
#