class FiniteMachine::EventsMap
A class responsible for storing mappings between event namess and their transition objects.
Used internally by {StateMachine}.
@api private
Public Class Methods
Initialize a EventsMap
@api private
# File lib/finite_machine/events_map.rb, line 24 def initialize @events_map = Concurrent::Map.new end
Public Instance Methods
Add transition under name
@param [Symbol] the event name
@param [Transition] transition
the transition to add under event name
@return [nil]
@api public
# File lib/finite_machine/events_map.rb, line 54 def add(name, transition) if exists?(name) @events_map[name] << transition else @events_map[name] = [transition] end self end
Check if event is valid and transition can be performed
@return [Boolean]
@api public
# File lib/finite_machine/events_map.rb, line 131 def can_perform?(name, from_state, *conditions) !match_transition_with(name, from_state, *conditions).nil? end
Check if event has branching choice transitions or not
@example
events_map.choice_transition?(:go, :green) # => true
@param [Symbol] name
the event name
@param [Symbol] from_state
the transition from state
@return [Boolean]
true if transition has any branches, false otherwise
@api public
# File lib/finite_machine/events_map.rb, line 150 def choice_transition?(name, from_state) find(name).select { |trans| trans.matches?(from_state) }.size > 1 end
Reset map
@return [self]
@api public
# File lib/finite_machine/events_map.rb, line 238 def clear @events_map.clear self end
Retrieve all event names
@example
events_map.events # => [:init, :start, :stop]
@return [Array]
All event names
@api public
# File lib/finite_machine/events_map.rb, line 88 def events @events_map.keys end
Check if event is present
@example
events_map.exists?(:go) # => true
@param [Symbol] name
the event name
@return [Boolean]
true if event is present, false otherwise
@api public
# File lib/finite_machine/events_map.rb, line 40 def exists?(name) @events_map.key?(name) end
Finds transitions for the event name
@param [Symbol] name
@example
events_map[:start] # => []
@return [Array]
the transitions matching event name
@api public
# File lib/finite_machine/events_map.rb, line 74 def find(name) @events_map.fetch(name) { [] } end
Inspect map content
@example
events_map.inspect
@return [String]
@api public
# File lib/finite_machine/events_map.rb, line 264 def inspect "<##{self.class} @events_map=#{self}>" end
Find transition without checking conditions
@param [Symbol] name
the event name
@param [Symbol] from_state
the transition from state
@return [Transition, nil]
returns transition, nil otherwise
@api private
# File lib/finite_machine/events_map.rb, line 166 def match_transition(name, from_state) find(name).find { |trans| trans.matches?(from_state) } end
Examine transitions for event name that start in from state and find one matching condition.
@param [Symbol] name
the event name
@param [Symbol] from_state
the current context from_state
@return [Transition]
The choice transition that matches
@api public
# File lib/finite_machine/events_map.rb, line 183 def match_transition_with(name, from_state, *conditions) find(name).find do |trans| trans.matches?(from_state) && trans.check_conditions(*conditions) end end
Find state that this machine can move to
@example
evenst_map.move_to(:go, :green) # => :red
@param [Symbol] name
the event name
@param [Symbol] from_state
the transition from state
@param [Array] conditions
the data associated with this transition
@return [Symbol]
the transition `to` state
@api public
# File lib/finite_machine/events_map.rb, line 227 def move_to(name, from_state, *conditions) transition = select_transition(name, from_state, *conditions) transition ||= UndefinedTransition.new(name) transition.to_state(from_state) end
Select transition that matches conditions
@param [Symbol] name
the event name
@param [Symbol] from_state
the transition from state
@param [Array] conditions
the conditional data
@return [Transition]
@api public
# File lib/finite_machine/events_map.rb, line 201 def select_transition(name, from_state, *conditions) if choice_transition?(name, from_state) match_transition_with(name, from_state, *conditions) else match_transition(name, from_state) end end
Retrieves all state transitions
@return [Array]
@api public
# File lib/finite_machine/events_map.rb, line 110 def state_transitions @events_map.values.flatten.map(&:states) end
Retreive all unique states
@example
events_map.states # => [:yellow, :green, :red]
@return [Array]
the array of all unique states
@api public
# File lib/finite_machine/events_map.rb, line 101 def states @events_map.values.flatten.map(&:states).map(&:to_a).flatten.uniq end
Retrieve from states for the event name
@param [Symbol] event_name
@example
events_map.states_for(:start) # => [:yellow, :green]
@api public
# File lib/finite_machine/events_map.rb, line 122 def states_for(name) find(name).map(&:states).flat_map(&:keys) end
Return string representation of this map
@return [String]
@api public
# File lib/finite_machine/events_map.rb, line 248 def to_s hash = {} @events_map.each_pair do |name, trans| hash[name] = trans end hash.to_s end