Class: ActiveComponent::Base

Inherits:
Object
  • Object
show all
Includes:
ActiveComponent, Enumerable, Haml::Helpers, Haml::Helpers::XssMods
Defined in:
lib/active_component/base.rb

Direct Known Subclasses

Block, EmptyTag, Heading, InlineTag, Section, Table

Constant Summary

Constants included from ActiveComponent

BLOCK_ELEMENTS, EMPTY_ELEMENTS, HEADING_ELEMENTS, HTML5_ELEMENTS, PHRASING_ELEMENTS, SECTION_ELEMENTS

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Enumerable

#find_a, #includes_a?, #transmogrify

Methods included from ActiveComponent

#print_contents, #print_object, #print_tag, #wrap_contents

Instance Attribute Details

#attributesObject

require ‘forwardable’ extend ::Forwardable



14
15
16
# File 'lib/active_component/base.rb', line 14

def attributes
  @attributes
end

#childrenHashObject

TODO: was not necessary to provide in Tree::TreeNode. Why here?



209
210
211
# File 'lib/active_component/base.rb', line 209

def childrenHash
  @childrenHash
end

#node_contentObject

node_content of this node. Can be nil.



206
207
208
# File 'lib/active_component/base.rb', line 206

def node_content
  @node_content
end

#node_nameObject

node_name of this node. Expected to be unique within the tree.



203
204
205
# File 'lib/active_component/base.rb', line 203

def node_name
  @node_name
end

#parentObject

Parent of this node. Will be nil for a root node.



212
213
214
# File 'lib/active_component/base.rb', line 212

def parent
  @parent
end

#titleObject

require ‘forwardable’ extend ::Forwardable



14
15
16
# File 'lib/active_component/base.rb', line 14

def title
  @title
end

Class Method Details

.def_component_helper(component_class) ⇒ Object

Raises:

  • (ArgumentError)


115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/active_component/base.rb', line 115

def self.def_component_helper(component_class)
  raise ArgumentError, "Anonymous classes are not allowed because a name is needed." if component_class.to_s =~ /#/

  ActiveComponent.class_eval do
    # New way of defining methods with a block parameter (1.9 only)
    # Attention: evaluation context seems to differ!
    #define_method(component_class.to_s.underscore) do |*args, &block|
      #component_class.new(*args, &block)
    #end

    # Old way of defining methods with a block parameter (supported by 1.8)
    eval %(
      def #{component_class.to_s.underscore}(*args, &block)
        #{component_class}.new(*args, &block)
      end
    )
  end
end

.def_html_sub_components(names, super_class) ⇒ Object

This helper creates HTML wrapper components that become sub classes of the given super_class (e.g. Section)



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/active_component/base.rb', line 135

def self.def_html_sub_components(names, super_class)
  for name in names
    # Creating an anonymous subclass and set according constant
    new_component = Object.const_set(name.to_s.camelize, Class.new(super_class))
    # Register component instantiation helper manually with the class constant
    def_component_helper(new_component)

    new_component.class_eval do
      # FIXME: Remove eval wrap as soon as Ruby 1.9.2 support can be dropped
      # Problem: "super from singleton method that is defined to multiple classes is not supported; this will be fixed in 1.9.3 or later"
      # See https://gist.github.com/455547
      eval %(
        def initialize(*args, &block)
          args << {:tag_type => self.class.to_s.underscore.to_sym}
          super *args, &block
        end
      )
    end
  end
end

.inherited(component_class) ⇒ Object



111
112
113
# File 'lib/active_component/base.rb', line 111

def self.inherited(component_class)
  def_component_helper(component_class) unless component_class.to_s =~ /#/
end

.json_create(json_hash) ⇒ Tree::TreeNode

Creates a Tree::TreeNode object instance from a given JSON Hash representation. This requires the JSON gem to be available, or else the operation fails with a warning message.

Parameters:

  • json_hash (Hash)

    The JSON hash to convert from.

Returns:

  • (Tree::TreeNode)

    The created tree.

See Also:

Author:

Since:

  • 0.7.0



817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
# File 'lib/active_component/base.rb', line 817

def self.json_create(json_hash)
  begin
    require 'json'

    node = new(json_hash["node_name"], json_hash["node_content"])

    json_hash["children"].each do |child|
      node << child
    end if json_hash["children"]

    return node
  rescue LoadError => e
    warn "The JSON gem couldn't be loaded. Due to this we cannot serialize the tree to a JSON representation."
  end
end

Instance Method Details

#<<(child) ⇒ Tree::TreeNode

Convenience synonym for Tree::TreeNode#add method.

This method allows an easy mechanism to add node hierarchies to the tree on a given path via chaining the method calls to successive child nodes.

Examples:

Add a child and grand-child to the root

root << child << grand_child

Parameters:

  • child (Tree::TreeNode)

    the child node to add.

Returns:

  • (Tree::TreeNode)

    The added child node.

See Also:

  • Tree::TreeNode#add


284
285
286
# File 'lib/active_component/base.rb', line 284

def <<(child)
  add(child)
end

#<=>(other) ⇒ Number

Provides a comparision operation for the nodes.

Comparision is based on the natural character-set ordering of the node node_name.

Parameters:

  • other (Tree::TreeNode)

    The other node to compare against.

Returns:

  • (Number)

    +1 if this node is a ‘successor’, 0 if equal and -1 if this node is a ‘predecessor’.



725
726
727
728
# File 'lib/active_component/base.rb', line 725

def <=>(other)
  return +1 if other == nil
  self.node_name <=> other.node_name
end

#[](node_name_or_index) ⇒ Tree::TreeNode

Returns the requested node from the set of immediate children.

If the argument is numeric, then the in-sequence array of children is accessed using the argument as the index (zero-based).

If the argument is NOT numeric, then it is taken to be the node_name of the child node to be returned.

An ArgumentError exception is raised if neither node_name nor an index is provided.

Parameters:

  • node_name_or_index (String|Number)

    node_name of the child, or its positional index in the array of child nodes.

Returns:

  • (Tree::TreeNode)

    the requested child node. If the index in not in range, or the node_name is not present, then a nil is returned.

Raises:

  • (ArgumentError)

    Raised if neither node_name nor index is provided.

See Also:



523
524
525
526
527
528
529
530
531
# File 'lib/active_component/base.rb', line 523

def [](node_name_or_index)
  raise ArgumentError, "node_name_or_index needs to be provided!" if node_name_or_index == nil

  if node_name_or_index.kind_of?(Integer)
    @children[node_name_or_index] || @childrenHash[node_name_or_index]
  else
    @childrenHash[node_name_or_index]
  end
end

#add(child, prepend = false) ⇒ Tree::TreeNode

Overridden / own methods


Adds the specified child node to the receiver node.

This method can also be used for grafting a subtree into the receiver node’s tree, if the specified child node is the root of a subtree (i.e., has child nodes under it).

The receiver node becomes parent of the node passed in as the argument, and the child is added as the last child (“right most”) in the current set of children of the receiver node.

node_name exists.

Parameters:

  • child (Tree::TreeNode)

    The child node to add.

Returns:

  • (Tree::TreeNode)

    The added child node.

Raises:

  • (RuntimeError)

    This exception is raised if another child node with the same

  • (ArgumentError)

    This exception is raised if a nil node is passed as the argument.

See Also:



184
185
186
187
188
189
190
191
192
193
# File 'lib/active_component/base.rb', line 184

def add(child, prepend = false)
  raise ArgumentError, "Attempting to add a nil node" unless child
  raise "Child #{child.node_name} already added!" if @childrenHash.has_key?(child.node_name)

  @childrenHash[child.node_name]  = child
  prepend ? @children.unshift(child) : (@children << child)
  raise "Great Scott! I just added a ghost child!" if !(@children.include?(child)) || @children.empty?
  child.parent = self
  child
end

#breadthNumber

Returns breadth of the tree at the receiver node’s level. A single node without siblings has a breadth of 1.

Breadth is defined to be:

Breadth

Number of sibling nodes to this node + 1 (this node itself),

i.e., the number of children the parent of this node has.

Returns:

  • (Number)

    breadth of the node’s level.



895
896
897
# File 'lib/active_component/base.rb', line 895

def breadth
  isRoot? ? 1 : parent.children.size
end

#breadth_each {|child| ... } ⇒ Object

Performs breadth-first traversal of the (sub)tree rooted at the receiver node. The traversal at a given level is from left-to-right. The receiver node itself is the first node to be traversed.

Yields:

  • (child)

    Each node is passed to the block.

Yield Parameters:

  • node (Tree::TreeNode)

    Each node.

See Also:



480
481
482
483
484
485
486
487
488
489
490
# File 'lib/active_component/base.rb', line 480

def breadth_each(&block)
  node_queue = [self]       # Create a queue with self as the initial entry

  # Use a queue to do breadth traversal
  until node_queue.empty?
    node_to_traverse = node_queue.shift
    yield node_to_traverse
    # Enqueue the children from left to right.
    node_to_traverse.children { |child| node_queue.push child }
  end
end

#children {|child| ... } ⇒ Array<Tree::TreeNode>

Returns an array of all the immediate children of the receiver node. The child nodes are ordered “left-to-right” in the returned array.

If a block is given, yields each child node to the block traversing from left to right.

Yields:

  • (child)

    Each child is passed to the block, if given

Yield Parameters:

  • child (Tree::TreeNode)

    Each child node.

Returns:

  • (Array<Tree::TreeNode>)

    An array of the child nodes, if no block is given.



418
419
420
421
422
423
424
# File 'lib/active_component/base.rb', line 418

def children
  if block_given?
    @children.each {|child| yield child}
  else
    @children
  end
end

#class_nameObject



95
96
97
# File 'lib/active_component/base.rb', line 95

def class_name
   self.class.to_s.hyphenize
end

#contentObject



83
84
85
86
# File 'lib/active_component/base.rb', line 83

def content
  # If content is not given yet, return node children
  @content || children
end

#content=(cont) ⇒ Object



75
76
77
78
79
80
81
# File 'lib/active_component/base.rb', line 75

def content=(cont)
  @content = cont
  # Add content as a child if it is also a component
  cont.transmogrify do |c|
    self << c if c.is_a? ActiveComponent
  end
end

#depthNumber

Deprecated.

This method returns an incorrect value. Use the ‘nodeDepth’ method instead.

Returns depth of the tree from the receiver node. A single leaf node has a depth of 1.

This method is DEPRECATED and may be removed in the subsequent releases. Note that the value returned by this method is actually the:

height + 1 of the node, NOT the depth.

For correct and conventional behavior, please use Tree::TreeNode#nodeDepth and Tree::TreeNode#nodeHeight methods instead.

Returns:

  • (Number)

    depth of the node.

See Also:



874
875
876
877
878
879
880
881
882
883
884
885
# File 'lib/active_component/base.rb', line 874

def depth
  begin
    require 'structured_warnings'   # To enable a nice way of deprecating of the depth method.
    warn DeprecatedMethodWarning, 'This method is deprecated.  Please use nodeDepth() or nodeHeight() instead (bug # 22535)'
  rescue LoadError
    # Oh well. Will use the standard Kernel#warn.  Behavior will be identical.
    warn 'Tree::TreeNode#depth() method is deprecated.  Please use nodeDepth() or nodeHeight() instead (bug # 22535)'
  end

  return 1 if isLeaf?
  1 + @children.collect { |child| child.depth }.max
end

#detached_copyTree::TreeNode

Returns a copy of the receiver node, with its parent and children links removed. The original node remains attached to its tree.

Returns:

  • (Tree::TreeNode)

    A copy of the receiver node.



237
238
239
# File 'lib/active_component/base.rb', line 237

def detached_copy
  Tree::TreeNode.new(@node_name, @node_content ? @node_content.clone : nil)
end

#each {|child| ... } ⇒ Object

Traverses each node (including the receiver node) of the (sub)tree rooted at this node by yielding the nodes to the specified block.

The traversal is depth-first and from left-to-right in pre-ordered sequence.

Yields:

  • (child)

    Each node is passed to the block.

Yield Parameters:

  • child (Tree::TreeNode)

    Each node.

See Also:



454
455
456
457
# File 'lib/active_component/base.rb', line 454

def each(&block)             # :yields: node
  yield self
  children { |child| child.each(&block) }
end

#each_leaf {|node| ... } ⇒ Object

Yields every leaf node of the (sub)tree rooted at the receiver node to the specified block.

May yield this node as well if this is a leaf node. Leaf traversal is depth-first and left-to-right.

Yields:

  • (node)

    Each leaf node is passed to the block.

Yield Parameters:

  • node (Tree::TreeNode)

    Each leaf node.

See Also:



502
503
504
# File 'lib/active_component/base.rb', line 502

def each_leaf &block
  self.each { |node| yield(node) if node.isLeaf? }
end

#firstChildTree::TreeNode

Returns the first child of the receiver node.

Will return nil if no children are present.

Returns:

  • (Tree::TreeNode)

    The first child, or nil if none is present.



431
432
433
# File 'lib/active_component/base.rb', line 431

def firstChild
  children.first
end

#firstSiblingTree::TreeNode

TODO:

Fix the inconsistency of returning root as its first sibling, and returning a nil array for siblings of the node.

Returns the first sibling of the receiver node. If this is the root node, then returns itself.

‘First’ sibling is defined as follows:

First sibling

The left-most child of the receiver’s parent, which may be the receiver itself

Returns:

  • (Tree::TreeNode)

    The first sibling node.

See Also:



603
604
605
# File 'lib/active_component/base.rb', line 603

def firstSibling
  isRoot? ? self : parent.children.first
end

#freezeTree!Object

Freezes all nodes in the (sub)tree rooted at the receiver node.

The nodes become immutable after this operation. In effect, the entire tree’s structure and node_contents become read-only and cannot be changed.



734
735
736
# File 'lib/active_component/base.rb', line 734

def freezeTree!
  each {|node| node.freeze}
end

#hasChildren?Boolean

Returns true if the receiver node has any child node.

Returns:

  • (Boolean)

    true if child nodes exist.

See Also:



395
396
397
# File 'lib/active_component/base.rb', line 395

def hasChildren?
  @children.length != 0
end

#hasnode_content?Boolean

Returns true if the receiver node has node_content.

Returns:

  • (Boolean)

    true if the node has node_content.



369
370
371
# File 'lib/active_component/base.rb', line 369

def hasnode_content?
  @node_content != nil
end

#html_classObject



88
89
90
91
92
93
# File 'lib/active_component/base.rb', line 88

def html_class
  class_arr = []
  class_arr << @title.hyphenize unless @title.blank?
  class_arr << class_name unless is_html_tag_wrapper?
  class_arr.uniq
end

#in_degreeNumber

Returns the incoming edge-count of the receiver node.

In-degree is defined as:

In-degree

The number of edges arriving at the node (0 for root, 1 for all other nodes)

  • In-degree = 0 for a root or orphaned node

  • In-degree = 1 for a node which has a parent

Returns:

  • (Number)

    The in-degree of this node.



908
909
910
# File 'lib/active_component/base.rb', line 908

def in_degree
  isRoot? ? 0 : 1
end

#init_component(args, var_names = [:content, :title, :attributes], &content_block) ⇒ Object

Initializes component by fetching arguments of a flexible method call as well as initializing the node and buffer Example

def initialize(*args, &content_block)
  fetch_args(args, [:content, :title, :special_param, :attributes], &content_block)

  # Set defaults afterwards
  @attributes ||= {:class => @title}
end

Arguments may be non-hash objects with certain order. Then, the arguments will be set to instance variables with the var_names entry at the same index. Though, it is always possible use a hash for assigning parameters to keywords (e.g. :title => “Blumenkübel”); As always, parenthesis can be omitted for this last hash.

The list of variable names will be iterated in order. The first element becomes an instance variable that gets the block assigned (if passed along). If the list of variable names iteration is complete, remaining key-value pairs of the Hash part of the arguments list are merged into @attributes.

Thus, all of the following signatures are legal for the **sender of fetch_args**: *Example 1*

new("content", "title", :class => "api")

*Example 2*

new(:class => "api", :title => "title") { content }

*Example 3*

new("content", {:attributes => {:class => "api"}, :title => "title"})

Parameters:

  • args (Array<Object>)

    Argument list where to fetch from

  • var_names (Array<Symbol>) (defaults to: [:content, :title, :attributes])

    Ordered list of instance variables to fetch. First one gets assigned to block (if given).

  • &content_block (#to_proc)

    The given block; will be assigned to variable named first in var_names.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/active_component/base.rb', line 47

def init_component(args, var_names = [:content, :title, :attributes], &content_block)

  init_node
  init_buffer

  # Fetch arguments
  non_hash_args = []
  args_hash     = {}
  # Collect all non-hash args and merge all hashs together
  for arg in args
    arg.is_a?(Hash) ? args_hash.merge!(arg) : non_hash_args << arg
  end

  # var_names.first is set to block if block given
  send(var_names.shift.to_s + "=", content_block.call) if content_block

  for var_name in var_names
    # Each value is extracted from args_hash, if resp. var_name present, otherwise the next non-hash argument is taken
    send var_name.to_s + "=", (args_hash.delete(var_name) or non_hash_args.shift)
  end

  @attributes ||= {}
  # All args in args_hash that have not been used for setting an instance variable become attributes.
  @attributes.set_defaults!(args_hash)
  # The class attribute will contain the component title and class_name (unless component is a html tag wrapper)
  @attributes[:class] = (html_class + [@attributes[:class]].flatten).compact.uniq
end

#init_node(node_name = object_id, node_content = nil) ⇒ Object

Creates a new node with a node_name and optional node_content. The node node_name is expected to be unique within the tree.

The node_content can be of any type, and defaults to nil.

Parameters:

  • node_name (Object) (defaults to: object_id)

    node_name of the node. Usual usage is to pass a String.

  • node_content (Object) (defaults to: nil)

    node_content of the node.

Raises:

  • (ArgumentError)

    Raised if the node node_name is empty.



224
225
226
227
228
229
230
231
# File 'lib/active_component/base.rb', line 224

def init_node(node_name = object_id, node_content = nil)
  raise ArgumentError, "Node node_name HAS to be provided!" if node_name == nil
  @node_name, @node_content = node_name, node_content

  self.setAsRoot!
  @childrenHash = Hash.new
  @children = []
end

#is_html_tag_wrapper?Boolean

Returns:

  • (Boolean)


107
108
109
# File 'lib/active_component/base.rb', line 107

def is_html_tag_wrapper?
  ActiveComponent::HTML5_ELEMENTS.each_value {|category| break true if category.include?(class_name.to_sym)} == true
end

#is_root?Boolean Also known as: isRoot?

Returns true if the receiver is a root node. Note that orphaned children will also be reported as root nodes.

Returns:

  • (Boolean)

    true if this is a root node.



384
385
386
# File 'lib/active_component/base.rb', line 384

def is_root?
  @parent.nil?
end

#isFirstSibling?Boolean

Returns true if the receiver node is the first sibling at its level.

Returns:

  • (Boolean)

    true if this is the first sibling.

See Also:



613
614
615
# File 'lib/active_component/base.rb', line 613

def isFirstSibling?
  firstSibling == self
end

#isLastSibling?Boolean

Returns true if the receiver node is the last sibling at its level.

Returns:

  • (Boolean)

    true if this is the last sibling.

See Also:



640
641
642
# File 'lib/active_component/base.rb', line 640

def isLastSibling?
  lastSibling == self
end

#isLeaf?Boolean

Returns true if the receiver node is a ‘leaf’ - i.e., one without any children.

Returns:

  • (Boolean)

    true if this is a leaf node.

See Also:



405
406
407
# File 'lib/active_component/base.rb', line 405

def isLeaf?
  !hasChildren?
end

#isOnlyChild?Boolean

Returns true if the receiver node is the only child of its parent.

As a special case, a root node will always return true.

Returns:

  • (Boolean)

    true if this is the only child of its parent.

See Also:



682
683
684
# File 'lib/active_component/base.rb', line 682

def isOnlyChild?
  isRoot? ? true : parent.children.size == 1
end

#lastChildTree::TreeNode

Returns the last child of the receiver node.

Will return nil if no children are present.

Returns:

  • (Tree::TreeNode)

    The last child, or nil if none is present.



440
441
442
# File 'lib/active_component/base.rb', line 440

def lastChild
  children.last
end

#lastSiblingTree::TreeNode

TODO:

Fix the inconsistency of returning root as its last sibling, and returning a nil array for siblings of the node.

Returns the last sibling of the receiver node. If this is the root node, then returns itself.

‘Last’ sibling is defined as follows:

Last sibling

The right-most child of the receiver’s parent, which may be the receiver itself

Returns:

  • (Tree::TreeNode)

    The last sibling node.

See Also:



630
631
632
# File 'lib/active_component/base.rb', line 630

def lastSibling
  isRoot? ? self : parent.children.last
end

#lengthNumber

Deprecated.

This method node_name is ambiguous and may be removed. Use TreeNode#size instead.

TODO:

The semantic of length is probably unclear. Should return the node depth instead to reflect the path length.

Convenience synonym for Tree::TreeNode#size.

Returns:

  • (Number)

    The total number of nodes in this (sub)tree.

See Also:



553
554
555
# File 'lib/active_component/base.rb', line 553

def length
  size()
end

#marshal_dumpObject

Returns a marshal-dump represention of the (sub)tree rooted at the receiver node.



739
740
741
# File 'lib/active_component/base.rb', line 739

def marshal_dump
  self.collect { |node| node.createDumpRep }
end

#marshal_load(dumped_tree_array) ⇒ Object

TODO:

This method probably should be a class method. It currently clobbers self and makes itself the root.

Loads a marshalled dump of a tree and returns the root node of the reconstructed tree. See the Marshal class for additional details.



755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
# File 'lib/active_component/base.rb', line 755

def marshal_load(dumped_tree_array)
  nodes = { }
  for node_hash in dumped_tree_array do
    node_name        = node_hash[:node_name]
    parent_node_name = node_hash[:parent]
    node_content     = Marshal.load(node_hash[:node_content])

    if parent_node_name then
      nodes[node_name] = current_node = Tree::TreeNode.new(node_name, node_content)
      nodes[parent_node_name].add current_node
    else
      # This is the root node, hence initialize self.
      initialize(node_name, node_content)

      nodes[node_name] = self    # Add self to the list of nodes
    end
  end
end

#nextSiblingTree::treeNode

Returns the next sibling for the receiver node. The ‘next’ node is defined as the node to right of the receiver node.

Will return nil if no subsequent node is present, or if the receiver is a root node.

Returns:

  • (Tree::treeNode)

    the next sibling node, if present.

See Also:



695
696
697
698
699
700
# File 'lib/active_component/base.rb', line 695

def nextSibling
  return nil if isRoot?
  if myidx = parent.children.index(self)
    parent.children.at(myidx + 1)
  end
end

#nodeDepthNumber Also known as: level

Returns depth of the receiver node in its tree. Depth of a node is defined as:

Depth

Length of the node’s path to its root. Depth of a root node is zero.

‘level’ is an alias for this method.

Returns:

  • (Number)

    Depth of this node.



853
854
855
856
# File 'lib/active_component/base.rb', line 853

def nodeDepth
  return 0 if isRoot?
  1 + parent.nodeDepth
end

#nodeHeightNumber

Returns height of the (sub)tree from the receiver node. Height of a node is defined as:

Height

Length of the longest downward path to a leaf from the node.

  • Height from a root node is height of the entire tree.

  • The height of a leaf node is zero.

Returns:

  • (Number)

    Height of the node.



841
842
843
844
# File 'lib/active_component/base.rb', line 841

def nodeHeight
  return 0 if isLeaf?
  1 + @children.collect { |child| child.nodeHeight }.max
end

#out_degreeNumber

Returns the outgoing edge-count of the receiver node.

Out-degree is defined as:

Out-degree

The number of edges leaving the node (zero for leafs)

Returns:

  • (Number)

    The out-degree of this node.



918
919
920
# File 'lib/active_component/base.rb', line 918

def out_degree
  isLeaf? ? 0 : children.size
end

#parentageArray?

Returns an array of ancestors of the receiver node in reversed order (the first element is the immediate parent of the receiver).

Returns nil if the receiver is a root node.

Returns:

  • (Array, nil)

    An array of ancestors of the receiver node, or nil if this is a root node.



248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/active_component/base.rb', line 248

def parentage
  return nil if isRoot?

  parentageArray = []
  prevParent = self.parent
  while (prevParent)
    parentageArray << prevParent
    prevParent = prevParent.parent
  end

  parentageArray
end

#preordered_each {|child| ... } ⇒ Object

Traverses the (sub)tree rooted at the receiver node in pre-ordered sequence. This is a synonym of Tree::TreeNode#each.

Yields:

  • (child)

    Each child is passed to the block.

Yield Parameters:

  • node (Tree::TreeNode)

    Each node.

See Also:



467
468
469
# File 'lib/active_component/base.rb', line 467

def preordered_each(&block)  # :yields: node
  each(&block)
end

#prepend(child) ⇒ Object



195
196
197
# File 'lib/active_component/base.rb', line 195

def prepend(child)
  add(child, true)
end

#previousSiblingTree::treeNode

Returns the previous sibling of the receiver node. ‘Previous’ node is defined to be the node to left of the receiver node.

Will return nil if no predecessor node is present, or if the receiver is a root node.

Returns:

  • (Tree::treeNode)

    the previous sibling node, if present.

See Also:



711
712
713
714
715
716
# File 'lib/active_component/base.rb', line 711

def previousSibling
  return nil if isRoot?
  if myidx = parent.children.index(self)
    parent.children.at(myidx - 1) if myidx > 0
  end
end

#printTree(level = 0) ⇒ Object

Pretty prints the (sub)tree rooted at the receiver node.

Parameters:

  • level (Number) (defaults to: 0)

    The indentation level (4 spaces) to start with.



560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
# File 'lib/active_component/base.rb', line 560

def printTree(level = 0)

  if isRoot?
    print "*"
  else
    print "|" unless parent.isLastSibling?
    print(' ' * (level - 1) * 4)
    print(isLastSibling? ? "+" : "|")
    print "---"
    print(hasChildren? ? "+" : ">")
  end

  puts " #{node_name}"

  children { |child| child.printTree(level + 1)}
end

#remove!(child) ⇒ Tree::TreeNode

Removes the specified child node from the receiver node.

This method can also be used for pruning a sub-tree, in cases where the removed child node is the root of the sub-tree to be pruned.

The removed child node is orphaned but accessible if an alternate reference exists. If accessible via an alternate reference, the removed child will report itself as a root node for its sub-tree.

Parameters:

  • child (Tree::TreeNode)

    The child node to remove.

Returns:

  • (Tree::TreeNode)

    The removed child node, or nil if a nil was passed in as argument.

See Also:



330
331
332
333
334
335
336
337
# File 'lib/active_component/base.rb', line 330

def remove!(child)
  return nil unless child

  @childrenHash.delete(child.node_name)
  @children.delete(child)
  child.setAsRoot!
  child
end

#removeAll!Tree::TreeNode

Removes all children from the receiver node. If an indepedent reference exists to the child nodes, then these child nodes report themselves as roots after this operation.

Returns:

  • (Tree::TreeNode)

    The receiver node (self)

See Also:



357
358
359
360
361
362
363
364
# File 'lib/active_component/base.rb', line 357

def removeAll!
  for child in @children
    child.setAsRoot!
  end
  @childrenHash.clear
  @children.clear
  self
end

#removeFromParent!Tree:TreeNode

Removes the receiver node from its parent. The reciever node becomes the new root for its subtree.

If this is the root node, then does nothing.

Returns:

  • (Tree:TreeNode)

    self (the removed receiver node) if the operation is successful, nil otherwise.

See Also:



346
347
348
# File 'lib/active_component/base.rb', line 346

def removeFromParent!
  @parent.remove!(self) unless isRoot?
end

#rootTree::TreeNode

TODO:

We should perhaps return nil as root’s root.

Returns root node for the (sub)tree to which the receiver node belongs.

Note that a root node’s root is itself (beware of any loop construct that may become infinite!)

Returns:

  • (Tree::TreeNode)

    Root of the (sub)tree.



584
585
586
587
588
# File 'lib/active_component/base.rb', line 584

def root
  root = self
  root = root.parent while !root.isRoot?
  root
end

#siblings {|sibling| ... } ⇒ Array<Tree::TreeNode>

TODO:

Fix the inconsistency of returning root as its own first/last sibling, and returning a nil array for siblings of the same root node.

TODO:

Also fix the inconsistency of returning nil for a root node, and an empty array for nodes which have no siblings.

Returns an array of siblings for the receiver node. The receiver node is excluded.

If a block is provided, yields each of the sibling nodes to the block. The root always has nil siblings.

Yields:

  • (sibling)

    Each sibling is passed to the block.

Yield Parameters:

  • sibling (Tree::TreeNode)

    Each sibling node.

Returns:

  • (Array<Tree::TreeNode>)

    Array of siblings of this node.

See Also:



661
662
663
664
665
666
667
668
669
670
671
672
673
# File 'lib/active_component/base.rb', line 661

def siblings
  return nil if is_root?

  if block_given?
    for sibling in parent.children
      yield sibling if sibling != self
    end
  else
    siblings = []
    parent.children {|my_sibling| siblings << my_sibling if my_sibling != self}
    siblings
  end
end

#sizeNumber

Returns the total number of nodes in this (sub)tree, including the receiver node.

Size of the tree is defined as:

Size

Total number nodes in the subtree including the receiver node.

Returns:

  • (Number)

    Total number of nodes in this (sub)tree.



540
541
542
# File 'lib/active_component/base.rb', line 540

def size
  @children.inject(1) {|sum, node| sum + node.size}
end

#to_htmlObject

Raises:

  • (NotImplementedError)


99
100
101
# File 'lib/active_component/base.rb', line 99

def to_html
  raise NotImplementedError, "to_html has to be implemented for every component that inherits from ActiveComponent::Base"
end

#to_json(*a) ⇒ Object

Creates a JSON representation of this node including all it’s children. This requires the JSON gem to be available, or else the operation fails with a warning message.

Returns:

  • The JSON representation of this subtree.

See Also:

Author:

Since:

  • 0.7.0



784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
# File 'lib/active_component/base.rb', line 784

def to_json(*a)
  begin
    require 'json'

    json_hash = {
      "node_name"         => node_name,
      "node_content"      => node_content,
      JSON.create_id => self.class.node_name
    }

    if hasChildren?
      json_hash["children"] = children
    end

    return json_hash.to_json

  rescue LoadError => e
    warn "The JSON gem couldn't be loaded. Due to this we cannot serialize the tree to a JSON representation"
  end
end

#to_sObject



103
104
105
# File 'lib/active_component/base.rb', line 103

def to_s
  to_html
end