class StateMachines::Branch
Represents a set of requirements that must be met in order for a transition or callback to occur. Branches verify that the event, from state, and to state of the transition match, in addition to if/unless conditionals for an object's state.
Attributes
The requirement for verifying the event being matched
The condition that must be met on an object
A list of all of the states known to this branch. This will pull states from the following options (in the same order):
-
from
/except_from
-
to
/except_to
One or more requirements for verifying the states being matched. All requirements contain a mapping of {:from => matcher, :to => matcher}.
The condition that must not be met on an object
Public Instance Methods
# File lib/state_machines/branch.rb, line 122 def draw(graph, event, valid_states) fail NotImplementedError end
Attempts to match the given object / query against the set of requirements configured for this branch. In addition to matching the event, from state, and to state, this will also check whether the configured :if/:unless conditions pass on the given object.
If a match is found, then the event/state requirements that the query passed successfully will be returned. Otherwise, nil is returned if there was no match.
Query options:
-
:from
- One or more states being transitioned from. If none are specified, then this will always match. -
:to
- One or more states being transitioned to. If none are specified, then this will always match. -
:on
- One or more events that fired the transition. If none are specified, then this will always match. -
:guard
- Whether to guard matches with the if/unless conditionals defined for this branch. Default is true.
Examples¶ ↑
branch = StateMachines::Branch.new(:parked => :idling, :on => :ignite) branch.match(object, :on => :ignite) # => {:to => ..., :from => ..., :on => ...} branch.match(object, :on => :park) # => nil
# File lib/state_machines/branch.rb, line 114 def match(object, query = {}) query.assert_valid_keys(:from, :to, :on, :guard) if (match = match_query(query)) && matches_conditions?(object, query) match end end
Determines whether the given object / query matches the requirements configured for this branch. In addition to matching the event, from state, and to state, this will also check whether the configured :if/:unless conditions pass on the given object.
Examples¶ ↑
branch = StateMachines::Branch.new(:parked => :idling, :on => :ignite) # Successful branch.matches?(object, :on => :ignite) # => true branch.matches?(object, :from => nil) # => true branch.matches?(object, :from => :parked) # => true branch.matches?(object, :to => :idling) # => true branch.matches?(object, :from => :parked, :to => :idling) # => true branch.matches?(object, :on => :ignite, :from => :parked, :to => :idling) # => true # Unsuccessful branch.matches?(object, :on => :park) # => false branch.matches?(object, :from => :idling) # => false branch.matches?(object, :to => :first_gear) # => false branch.matches?(object, :from => :parked, :to => :first_gear) # => false branch.matches?(object, :on => :park, :from => :parked, :to => :idling) # => false
# File lib/state_machines/branch.rb, line 85 def matches?(object, query = {}) !match(object, query).nil? end
Protected Instance Methods
Builds a matcher strategy to use for the given options. If neither a whitelist nor a blacklist option is specified, then an AllMatcher is built.
# File lib/state_machines/branch.rb, line 130 def build_matcher(options, whitelist_option, blacklist_option) options.assert_exclusive_keys(whitelist_option, blacklist_option) if options.include?(whitelist_option) value = options[whitelist_option] value.is_a?(Matcher) ? value : WhitelistMatcher.new(options[whitelist_option]) elsif options.include?(blacklist_option) value = options[blacklist_option] raise ArgumentError, ":#{blacklist_option} option cannot use matchers; use :#{whitelist_option} instead" if value.is_a?(Matcher) BlacklistMatcher.new(value) else AllMatcher.instance end end
Verifies that the event requirement matches the given query
# File lib/state_machines/branch.rb, line 157 def match_event(query) matches_requirement?(query, :on, event_requirement) end
Verifies that all configured requirements (event and state) match the given query. If a match is found, then a hash containing the event/state requirements that passed will be returned; otherwise, nil.
# File lib/state_machines/branch.rb, line 148 def match_query(query) query ||= {} if match_event(query) && (state_requirement = match_states(query)) state_requirement.merge(:on => event_requirement) end end
Verifies that the state requirements match the given query. If a matching requirement is found, then it is returned.
# File lib/state_machines/branch.rb, line 163 def match_states(query) state_requirements.detect do |state_requirement| [:from, :to].all? {|option| matches_requirement?(query, option, state_requirement[option])} end end
Verifies that the conditionals for this branch evaluate to true for the given object
# File lib/state_machines/branch.rb, line 177 def matches_conditions?(object, query) query[:guard] == false || Array(if_condition).all? {|condition| evaluate_method(object, condition)} && !Array(unless_condition).any? {|condition| evaluate_method(object, condition)} end
Verifies that an option in the given query matches the values required for that option
# File lib/state_machines/branch.rb, line 171 def matches_requirement?(query, option, requirement) !query.include?(option) || requirement.matches?(query[option], query) end