Class | StateMachine::NodeCollection |
In: |
lib/state_machine/node_collection.rb
|
Parent: | Object |
Represents a collection of nodes in a state machine, be it events or states. Nodes will not differentiate between the String and Symbol versions of the values being indexed.
machine | [R] | The machine associated with the nodes |
Creates a new collection of nodes for the given state machine. By default, the collection is empty.
Configuration options:
# File lib/state_machine/node_collection.rb, line 21 21: def initialize(machine, options = {}) 22: assert_valid_keys(options, :index) 23: options = {:index => :name}.merge(options) 24: 25: @machine = machine 26: @nodes = [] 27: @index_names = Array(options[:index]) 28: @indices = @index_names.inject({}) do |indices, name| 29: indices[name] = {} 30: indices["#{name}_to_s""#{name}_to_s"] = {} 31: indices["#{name}_to_sym""#{name}_to_sym"] = {} 32: indices 33: end 34: @default_index = Array(options[:index]).first 35: @contexts = [] 36: end
Adds a new node to the collection. By doing so, this will also add it to the configured indices. This will also evaluate any existings contexts that match the new node.
# File lib/state_machine/node_collection.rb, line 88 88: def <<(node) 89: @nodes << node 90: @index_names.each {|name| add_to_index(name, value(node, name), node)} 91: @contexts.each {|context| eval_context(context, node)} 92: self 93: end
Gets the node indexed by the given key. By default, this will look up the key in the first index configured for the collection. A custom index can be specified like so:
collection['parked', :value]
The above will look up the "parked" key in a hash indexed by each node‘s value attribute.
If the key cannot be found, then nil will be returned.
# File lib/state_machine/node_collection.rb, line 145 145: def [](key, index_name = @default_index) 146: self.index(index_name)[key] || 147: self.index("#{index_name}_to_s""#{index_name}_to_s")[key.to_s] || 148: to_sym?(key) && self.index("#{index_name}_to_sym""#{index_name}_to_sym")["#{key}""#{key}"] || 149: nil 150: end
Gets the node at the given index.
states = StateMachine::NodeCollection.new states << StateMachine::State.new(machine, :parked) states << StateMachine::State.new(machine, :idling) states.at(0).name # => :parked states.at(1).name # => :idling
# File lib/state_machine/node_collection.rb, line 131 131: def at(index) 132: @nodes[index] 133: end
Appends a group of nodes to the collection
# File lib/state_machine/node_collection.rb, line 96 96: def concat(nodes) 97: nodes.each {|node| self << node} 98: end
Tracks a context that should be evaluated for any nodes that get added which match the given set of nodes. Matchers can be used so that the context can get added once and evaluated after multiple adds.
# File lib/state_machine/node_collection.rb, line 75 75: def context(nodes, &block) 76: nodes = nodes.first.is_a?(Matcher) ? nodes.first : WhitelistMatcher.new(nodes) 77: @contexts << context = {:nodes => nodes, :block => block} 78: 79: # Evaluate the new context for existing nodes 80: each {|node| eval_context(context, node)} 81: 82: context 83: end
Calls the block once for each element in self, passing that element as a parameter.
states = StateMachine::NodeCollection.new states << StateMachine::State.new(machine, :parked) states << StateMachine::State.new(machine, :idling) states.each {|state| puts state.name, ' -- '}
…produces:
parked -- idling --
# File lib/state_machine/node_collection.rb, line 118 118: def each 119: @nodes.each {|node| yield node} 120: self 121: end
Gets the node indexed by the given key. By default, this will look up the key in the first index configured for the collection. A custom index can be specified like so:
collection['parked', :value]
The above will look up the "parked" key in a hash indexed by each node‘s value attribute.
If the key cannot be found, then an IndexError exception will be raised:
collection['invalid', :value] # => IndexError: "invalid" is an invalid value
# File lib/state_machine/node_collection.rb, line 164 164: def fetch(key, index_name = @default_index) 165: self[key, index_name] || raise(IndexError, "#{key.inspect} is an invalid #{index_name}") 166: end
Gets the number of nodes in this collection
# File lib/state_machine/node_collection.rb, line 63 63: def length 64: @nodes.length 65: end
Changes the current machine associated with the collection. In turn, this will change the state machine associated with each node in the collection.
# File lib/state_machine/node_collection.rb, line 57 57: def machine=(new_machine) 58: @machine = new_machine 59: each {|node| node.machine = new_machine} 60: end
Updates the indexed keys for the given node. If the node‘s attribute has changed since it was added to the collection, the old indexed keys will be replaced with the updated ones.
# File lib/state_machine/node_collection.rb, line 103 103: def update(node) 104: @index_names.each {|name| update_index(name, node)} 105: end
Adds the given key / node combination to an index, including the string and symbol versions of the index
# File lib/state_machine/node_collection.rb, line 183 183: def add_to_index(name, key, node) 184: index(name)[key] = node 185: index("#{name}_to_s""#{name}_to_s")[key.to_s] = node 186: index("#{name}_to_sym""#{name}_to_sym")["#{key}""#{key}"] = node if to_sym?(key) 187: end
Gets the given index. If the index does not exist, then an ArgumentError is raised.
# File lib/state_machine/node_collection.rb, line 171 171: def index(name) 172: raise ArgumentError, 'No indices configured' unless @indices.any? 173: @indices[name] || raise(ArgumentError, "Invalid index: #{name.inspect}") 174: end
Removes the given key from an index, including the string and symbol versions of the index
# File lib/state_machine/node_collection.rb, line 191 191: def remove_from_index(name, key) 192: index(name).delete(key) 193: index("#{name}_to_s""#{name}_to_s").delete(key.to_s) 194: index("#{name}_to_sym""#{name}_to_sym").delete("#{key}""#{key}") if to_sym?(key) 195: end
Updates the node for the given index, including the string and symbol versions of the index
# File lib/state_machine/node_collection.rb, line 199 199: def update_index(name, node) 200: index = self.index(name) 201: old_key = RUBY_VERSION < '1.9' ? index.index(node) : index.key(node) 202: new_key = value(node, name) 203: 204: # Only replace the key if it's changed 205: if old_key != new_key 206: remove_from_index(name, old_key) 207: add_to_index(name, new_key, node) 208: end 209: end