class Trivet::Childset
Objects of this class act like an array of the children of a node. However, unlike an array, attempts to add children result in calling Trivet::Node#allow_child?
to check if the child is allowed.
Attributes
Returns the Trivet::Node
object that this object is attached to.
Public Class Methods
Accepts a Trivet::Node
object to which this object will be attached.
# File lib/trivet.rb, line 1109 def initialize(node) @node = node @children = [] end
Public Instance Methods
Shortcut for append without any options.
# File lib/trivet.rb, line 1186 def <<(new_child) return append(new_child) end
Adds a child to the end of the array. Calls Trivet::Node#allow_child?
to check if the child can be added. Does nothing if the node is already a child.
# File lib/trivet.rb, line 1181 def append(new_child, opts={}) return add_child(new_child, 'last', opts) end
Removes all children.
# File lib/trivet.rb, line 1223 def clear() # explicitly unlink childen @children.clone.each do |child| if child.is_a?(Trivet::Node) child.unlink end end # remove all other child objects @children.clear end
Returns true if the @children contains the given object. This method is not quite the same as include?. This method returns true only if @children contains the actual object given, not just an object that matches ==. So, for example, the following use of have_object? would return false, even though it cohtains a string identical to the string in @children.
@children.push 'whatever' @children.include? 'whatever' # true @children.have_object? 'whatever' # false
# File lib/trivet.rb, line 1339 def have_object?(potential) @children.each_with_index do |child, idx| if child.equal?(potential) return idx end end return false end
Inserts the child at the position indicated by index. Calls Trivet::Node#allow_child?
to check if the child can be added. Does nothing if the node is already a child.
# File lib/trivet.rb, line 1200 def insert(index, new_child, opts={}) return add_child(new_child, index, opts) end
Unlinks and returns the last child. Returns nil if there are no children.
# File lib/trivet.rb, line 1266 def pop() # remove first element removed = @children.pop # if a node was removed, unlink it if removed.is_a?(Trivet::Node) removed.unlink 'recurse'=>false end # return return removed end
Adds a child to the end of the array. Calls Trivet::Node#allow_child?
to check if the child can be added. Does nothing if the node is already a child.
# File lib/trivet.rb, line 1174 def push(new_child, opts={}) return add_child(new_child, 'last', opts) end
Acts like Array#reject!. Rejected children are unlinked.
# File lib/trivet.rb, line 1288 def reject!() # If no block, just return an enumerator. This mimics the behavior of # Array#reject!. if not block_given? return enum_for(:each) end # $tm.hrm all = @children.clone # loop through all all.each do |child| bool = yield(child) bool or remove_object(child) end # return return self end
Removes the given child from the array of children. Does nothing if the child isn't present.
# File lib/trivet.rb, line 1214 def remove_object(child, opts={}) # opts = {'recurse'=>true}.merge(opts) @children.reject!() do |el| el.equal? child end end
Unlinks and returns the first child. Returns nil if there are no children.
# File lib/trivet.rb, line 1244 def shift() # remove first element removed = @children.shift # if a node was removed, unlink it if removed.is_a?(Trivet::Node) removed.unlink 'recurse'=>false end # return return removed end
Returns an array of the children.
# File lib/trivet.rb, line 1317 def to_a return @children.clone end
Adds a child to the beginning of the array. Calls Trivet::Node#allow_child?
to check if the child can be added. Does nothing if the node is already a child.
# File lib/trivet.rb, line 1193 def unshift(new_child, opts={}) return add_child(new_child, 'first', opts) end
Private Instance Methods
# File lib/trivet.rb, line 1360 def add_child(new_child, index, opts) opts = {'recurse'=>true}.merge(opts) # check if this parent is allowed to have this child if not @node.allow_child?(new_child) if new_child.respond_to?('to_debug') child_debug = new_child.to_debug elsif new_child.is_a?(String) child_debug = new_child else child_debug = '[unrecognized object]' end raise 'parent-cannot-have-this-child: ' + @node.to_debug + ' / ' + child_debug end # add to children if not already there # if dup_ok or (not @children.include?(new_child)) if (not have_object?(new_child)) # add to start of array if index == 'first' @children.unshift new_child # add to end of array elsif index == 'last' @children.push new_child # insert at specific index elsif index.is_a?(Integer) # don't allow insert past end of array if index > @children.length raise 'add-child-cannot-insert-past-end' end # insert @children.insert index, new_child # else unknown index else puts 'add-child-invalid-index: ' + index.to_s end # set node's parent if necessary if opts['recurse'] and new_child.is_a?(Trivet::Node) new_child.set_parent @node, 'recurse'=>false end end # always return self return self end