rubytree 1.0.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/API-CHANGES.md +153 -0
- data/Gemfile +2 -6
- data/Gemfile.lock +40 -55
- data/History.md +410 -0
- data/LICENSE.md +1 -1
- data/README.md +21 -24
- data/Rakefile +41 -20
- data/TODO.org +19 -15
- data/examples/example_basic.rb +14 -7
- data/lib/rubytree.rb +2 -3
- data/lib/tree/binarytree.rb +13 -12
- data/lib/tree/tree_deps.rb +2 -5
- data/lib/tree/utils/hash_converter.rb +129 -121
- data/lib/tree/utils/json_converter.rb +80 -77
- data/lib/tree/utils/metrics_methods.rb +14 -47
- data/lib/tree/utils/path_methods.rb +11 -11
- data/lib/tree/utils/tree_merge_handler.rb +80 -80
- data/lib/tree/utils/utils.rb +9 -7
- data/lib/tree/version.rb +3 -4
- data/lib/tree.rb +80 -82
- data/rubytree.gemspec +61 -38
- data/spec/spec_helper.rb +4 -2
- data/spec/tree_spec.rb +129 -28
- data/test/run_test.rb +4 -3
- data/test/test_binarytree.rb +25 -45
- data/test/test_rubytree_require.rb +2 -1
- data/test/test_subclassed_node.rb +2 -20
- data/test/test_thread_and_fiber.rb +4 -4
- data/test/test_tree.rb +126 -199
- metadata +103 -69
- data/API-CHANGES.rdoc +0 -99
- data/History.rdoc +0 -303
- data/lib/tree/utils/camel_case_method_handler.rb +0 -77
- data/setup.rb +0 -1565
data/TODO.org
CHANGED
@@ -183,10 +183,7 @@
|
|
183
183
|
This proposed change does make sense at one level (since the root node does not have any parent), but returning root
|
184
184
|
as root's root (no pun intended) makes accessing the root from anywhere in the tree much easier.
|
185
185
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
* R0.9.5
|
186
|
+
* R0.9.5 :ARCHIVE:
|
190
187
|
** DONE Add the `#get_path_as_string` method from feature request #48 :ARCHIVE:
|
191
188
|
CLOSED: [2015-05-30 Sat 15:55]
|
192
189
|
** DONE Fix [[Issue:32][Issue #32]] and enable move semantics on the TreeNode#add method. :ARCHIVE:
|
@@ -202,11 +199,20 @@
|
|
202
199
|
CLOSED: [2014-11-01 Sat 20:11]
|
203
200
|
|
204
201
|
|
202
|
+
* R2.0.0
|
203
|
+
|
204
|
+
This is primarily a *modernization* of the library, with removal of deprecated methods, the much-hated dependency on
|
205
|
+
~structured_warnings~, and cleanup of other cruft.
|
206
|
+
|
207
|
+
In addition, the CI pipeline has been moved from <https://travis.ci> to ~Github Actions~.
|
205
208
|
|
209
|
+
- [X] Merge the modernization PR from @jmortlock (multiple changes).
|
210
|
+
- [X] Update the documentation to reflect the modernization changes.
|
206
211
|
|
207
|
-
|
208
|
-
|
209
|
-
|
212
|
+
|
213
|
+
* Unplanned / Not assigned to any release
|
214
|
+
*** STARTED Convert all documentation to markdown mode.
|
215
|
+
*** STARTED [#A] Resolve the infinite loop bug if a node is added to itself as a child :Partial:
|
210
216
|
[[Issue:5][Issue #5.]]
|
211
217
|
|
212
218
|
This is a subtle problem to resolve. The specific case of a node
|
@@ -237,15 +243,8 @@
|
|
237
243
|
duplicates). This needs to be a hash (to allow O(1) access),
|
238
244
|
and will sacrifice memory. There might be a need to
|
239
245
|
restructure the internals to make better use of memory.
|
240
|
-
|
241
|
-
** TODO Expand the examples section, and add supporting documentation
|
246
|
+
*** TODO Expand the examples section, and add supporting documentation
|
242
247
|
|
243
|
-
* Unplanned / Not assigned to any release
|
244
|
-
*** DONE [#A] Migrate the website and references from http://rubyforge.org/ :ARCHIVE:
|
245
|
-
CLOSED: [2014-07-04 Fri 22:18]
|
246
|
-
*** DONE Revert the forced install of rubygem 2.1.11 from [[file:.travis.yml][.travis.yml]] :ARCHIVE:
|
247
|
-
CLOSED: [2014-01-12 Sun 19:06]
|
248
|
-
The issue seems to have been resolved with the 2.2.1 release of Rubygems.
|
249
248
|
*** TODO Create a cycle-detection/validation mechanism to prevent cyclic graphs of nodes.
|
250
249
|
*** TODO Create a generic validation method to check for various issues in the created tree.
|
251
250
|
*** TODO Add a FAQ document to the project.
|
@@ -258,6 +257,11 @@
|
|
258
257
|
*** TODO Add a YAML export method to the TreeNode class.
|
259
258
|
|
260
259
|
*** TODO marshal_load method probably should be a class method. It currently clobbers self.
|
260
|
+
*** DONE Revert the forced install of rubygem 2.1.11 from [[file:.travis.yml][.travis.yml]] :ARCHIVE:
|
261
|
+
CLOSED: [2014-01-12 Sun 19:06]
|
262
|
+
The issue seems to have been resolved with the 2.2.1 release of Rubygems.
|
263
|
+
*** DONE [#A] Migrate the website and references from http://rubyforge.org/ :ARCHIVE:
|
264
|
+
CLOSED: [2014-07-04 Fri 22:18]
|
261
265
|
*** DONE Fix bug # [[http://rubyforge.org/tracker/index.php%3Ffunc%3Ddetail&aid%3D22535&group_id%3D1215&atid%3D4793][22535]]: The method Tree::TreeNode#depth is a misnomer. The current definition actually provides the height function. :ARCHIVE:
|
262
266
|
DEADLINE: <2010-01-09 Sat> CLOSED: [2010-01-03 Sun 22:15]
|
263
267
|
|
data/examples/example_basic.rb
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
# example_basic.rb:: Basic usage of the tree library.
|
4
4
|
#
|
5
5
|
# Author: Anupam Sengupta
|
6
|
-
# Time-stamp: <
|
7
|
-
# Copyright (C) 2013, 2015 Anupam Sengupta <anupamsg@gmail.com>
|
6
|
+
# Time-stamp: <2022-06-19 22:52:29 anupam>
|
7
|
+
# Copyright (C) 2013, 2015, 2022 Anupam Sengupta <anupamsg@gmail.com>
|
8
8
|
#
|
9
9
|
# The following example implements this tree structure:
|
10
10
|
#
|
@@ -21,22 +21,29 @@
|
|
21
21
|
# +-------+-------+
|
22
22
|
# | GRANDCHILD 1 |
|
23
23
|
# +---------------+
|
24
|
+
#
|
25
|
+
# frozen_string_literal: true
|
24
26
|
|
25
27
|
# ..... Example starts.
|
26
28
|
require 'tree' # Load the library
|
27
29
|
|
28
|
-
# ..... Create the root node first.
|
30
|
+
# ..... Create the root node first. Note that every node has a name and an
|
31
|
+
# ..... optional content payload.
|
29
32
|
root_node = Tree::TreeNode.new('ROOT', 'Root Content')
|
30
33
|
root_node.print_tree
|
31
34
|
|
32
|
-
# ..... Now insert the child nodes.
|
33
|
-
|
35
|
+
# ..... Now insert the child nodes. Note that you can "chain" the child
|
36
|
+
# ..... insertions for a given path to any depth.
|
37
|
+
root_node << Tree::TreeNode.new('CHILD1', 'Child1 Content') \
|
38
|
+
<< Tree::TreeNode.new('GRANDCHILD1', 'GrandChild1 Content')
|
34
39
|
root_node << Tree::TreeNode.new('CHILD2', 'Child2 Content')
|
35
40
|
|
36
|
-
# ..... Lets print the representation to stdout.
|
41
|
+
# ..... Lets print the representation to stdout. This is primarily used for
|
42
|
+
# ..... debugging purposes.
|
37
43
|
root_node.print_tree
|
38
44
|
|
39
|
-
# ..... Lets directly access children and grandchildren of the root.
|
45
|
+
# ..... Lets directly access children and grandchildren of the root. The can be
|
46
|
+
# ..... "chained" for a given path to any depth.
|
40
47
|
child1 = root_node['CHILD1']
|
41
48
|
grand_child1 = root_node['CHILD1']['GRANDCHILD1']
|
42
49
|
|
data/lib/rubytree.rb
CHANGED
@@ -8,9 +8,7 @@
|
|
8
8
|
#
|
9
9
|
# Author:: Anupam Sengupta (anupamsg@gmail.com)
|
10
10
|
#
|
11
|
-
# Copyright (c) 2012
|
12
|
-
#
|
13
|
-
# All rights reserved.
|
11
|
+
# Copyright (c) 2012-2022 Anupam Sengupta. All rights reserved.
|
14
12
|
#
|
15
13
|
# Redistribution and use in source and binary forms, with or without
|
16
14
|
# modification, are permitted provided that the following conditions are met:
|
@@ -37,5 +35,6 @@
|
|
37
35
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
38
36
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
39
37
|
#
|
38
|
+
# frozen_string_literal: true
|
40
39
|
|
41
40
|
require 'tree'
|
data/lib/tree/binarytree.rb
CHANGED
@@ -8,9 +8,7 @@
|
|
8
8
|
# Author:: Anupam Sengupta (anupamsg@gmail.com)
|
9
9
|
#
|
10
10
|
|
11
|
-
# Copyright (c) 2007
|
12
|
-
#
|
13
|
-
# All rights reserved.
|
11
|
+
# Copyright (c) 2007-2022 Anupam Sengupta. All rights reserved.
|
14
12
|
#
|
15
13
|
# Redistribution and use in source and binary forms, with or without
|
16
14
|
# modification, are permitted provided that the following conditions are met:
|
@@ -37,6 +35,7 @@
|
|
37
35
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
38
36
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
39
37
|
#
|
38
|
+
# frozen_string_literal: true
|
40
39
|
|
41
40
|
require_relative '../tree'
|
42
41
|
|
@@ -76,28 +75,32 @@ module Tree
|
|
76
75
|
children[1]
|
77
76
|
end
|
78
77
|
|
79
|
-
# @!attribute
|
78
|
+
# @!attribute left_child?
|
80
79
|
# +true+ if the receiver node is the left child of its parent.
|
81
80
|
# Always returns +false+ if it is a root node.
|
82
81
|
#
|
83
82
|
# @return [Boolean] +true+ if this is the left child of its parent.
|
84
|
-
def
|
85
|
-
return false if
|
83
|
+
def left_child?
|
84
|
+
return false if root?
|
86
85
|
|
87
86
|
self == parent.left_child
|
88
87
|
end
|
89
88
|
|
90
|
-
#
|
89
|
+
alias is_left_child? left_child? # @todo: Aliased for eventual replacement
|
90
|
+
|
91
|
+
# @!attribute [r] right_child?
|
91
92
|
# +true+ if the receiver node is the right child of its parent.
|
92
93
|
# Always returns +false+ if it is a root node.
|
93
94
|
#
|
94
95
|
# @return [Boolean] +true+ if this is the right child of its parent.
|
95
|
-
def
|
96
|
-
return false if
|
96
|
+
def right_child?
|
97
|
+
return false if root?
|
97
98
|
|
98
99
|
self == parent.right_child
|
99
100
|
end
|
100
101
|
|
102
|
+
alias is_right_child? right_child? # @todo: Aliased for eventual replacement
|
103
|
+
|
101
104
|
# @!group Structure Modification
|
102
105
|
|
103
106
|
# Adds the specified child node to the receiver node. The child node's
|
@@ -164,8 +167,6 @@ module Tree
|
|
164
167
|
#
|
165
168
|
# @since 0.9.0
|
166
169
|
#
|
167
|
-
# @param [Object] block
|
168
|
-
#
|
169
170
|
# @see #each
|
170
171
|
# @see #preordered_each
|
171
172
|
# @see #postordered_each
|
@@ -176,7 +177,7 @@ module Tree
|
|
176
177
|
node_stack = []
|
177
178
|
current_node = self
|
178
179
|
|
179
|
-
until node_stack.empty?
|
180
|
+
until node_stack.empty? && current_node.nil?
|
180
181
|
if current_node
|
181
182
|
node_stack.push(current_node)
|
182
183
|
current_node = current_node.left_child
|
data/lib/tree/tree_deps.rb
CHANGED
@@ -7,9 +7,7 @@
|
|
7
7
|
# Author:: Anupam Sengupta (anupamsg@gmail.com)
|
8
8
|
#
|
9
9
|
|
10
|
-
# Copyright (c) 2006-
|
11
|
-
#
|
12
|
-
# All rights reserved.
|
10
|
+
# Copyright (c) 2006-2022 Anupam Sengupta. All rights reserved.
|
13
11
|
#
|
14
12
|
# Redistribution and use in source and binary forms, with or without
|
15
13
|
# modification, are permitted provided that the following conditions are met:
|
@@ -36,14 +34,13 @@
|
|
36
34
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
37
35
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
38
36
|
#
|
37
|
+
# frozen_string_literal: true
|
39
38
|
|
40
|
-
require 'structured_warnings'
|
41
39
|
require 'json'
|
42
40
|
|
43
41
|
require_relative '../tree/version'
|
44
42
|
require_relative '../tree/utils/metrics_methods'
|
45
43
|
require_relative '../tree/utils/path_methods'
|
46
|
-
require_relative '../tree/utils/camel_case_method_handler'
|
47
44
|
require_relative '../tree/utils/json_converter'
|
48
45
|
require_relative '../tree/utils/tree_merge_handler'
|
49
46
|
require_relative '../tree/utils/hash_converter'
|
@@ -5,9 +5,9 @@
|
|
5
5
|
#
|
6
6
|
# Author:: Jen Hamon (http://www.github.com/jhamon)
|
7
7
|
#
|
8
|
-
# Time-stamp: <
|
8
|
+
# Time-stamp: <2022-06-20 22:16:39 anupam>
|
9
9
|
#
|
10
|
-
# Copyright (C) 2014, 2015 Jen Hamon (http://www.github.com/jhamon) and
|
10
|
+
# Copyright (C) 2014, 2015, 2022, 2022 Jen Hamon (http://www.github.com/jhamon) and
|
11
11
|
# Anupam Sengupta <anupamsg@gmail.com>
|
12
12
|
#
|
13
13
|
# All rights reserved.
|
@@ -36,138 +36,146 @@
|
|
36
36
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
37
37
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
38
38
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
39
|
+
#
|
40
|
+
# frozen_string_literal: true
|
39
41
|
|
40
|
-
|
42
|
+
module Tree
|
43
|
+
module Utils
|
44
|
+
# Provides a utility for marshalling/unmarshalling TreeNode objects to Ruby
|
45
|
+
# +hash+ objects.
|
46
|
+
#
|
47
|
+
# @author Jen Hamon (https://www.github.com/jhamon)
|
48
|
+
module HashConverter
|
49
|
+
def self.included(base)
|
50
|
+
base.extend(ClassMethods)
|
51
|
+
end
|
41
52
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
53
|
+
# Methods in {Tree::Utils::HashConverter::ClassMethods} will be added as
|
54
|
+
# class methods on any class mixing in the {Tree::Utils::HashConverter}
|
55
|
+
# module.
|
56
|
+
module ClassMethods
|
57
|
+
# Factory method builds a {Tree::TreeNode} from a +Hash+.
|
58
|
+
#
|
59
|
+
# This method will interpret each key of your +Hash+ as a {Tree::TreeNode}.
|
60
|
+
# Nested hashes are expected and child nodes will be added accordingly. If
|
61
|
+
# a hash key is a single value that value will be used as the name for the
|
62
|
+
# node. If a hash key is an Array, both node name and content will be
|
63
|
+
# populated.
|
64
|
+
#
|
65
|
+
# A leaf element of the tree should be represented as a hash key with
|
66
|
+
# corresponding value +nil+ or +{}+.
|
67
|
+
#
|
68
|
+
# @example
|
69
|
+
# TreeNode.from_hash({:A => {:B => {}, :C => {:D => {}, :E => {}}}})
|
70
|
+
# # would be parsed into the following tree structure:
|
71
|
+
# # A
|
72
|
+
# # / \
|
73
|
+
# # B C
|
74
|
+
# # / \
|
75
|
+
# # D E
|
76
|
+
#
|
77
|
+
# # The same tree would result from this nil-terminated Hash
|
78
|
+
# {:A => {:B => nil, :C => {:D => nil, :E => nil}}}
|
79
|
+
#
|
80
|
+
# # A tree with equivalent structure but with content present for
|
81
|
+
# # nodes A and D could be built from a hash like this:
|
82
|
+
# {[:A, "A content"] => {:B => {},
|
83
|
+
# :C => { [:D, "D content"] => {},
|
84
|
+
# :E => {} }}}
|
85
|
+
#
|
86
|
+
# @author Jen Hamon (http://www.github.com/jhamon)
|
87
|
+
# @param [Hash] hash Hash to build tree from.
|
88
|
+
#
|
89
|
+
# @return [Tree::TreeNode] The {Tree::TreeNode} instance representing the
|
90
|
+
# root of your tree.
|
91
|
+
#
|
92
|
+
# @raise [ArgumentError] This exception is raised if a non-Hash is passed.
|
93
|
+
#
|
94
|
+
# @raise [ArgumentError] This exception is raised if the hash has multiple
|
95
|
+
# top-level elements.
|
96
|
+
#
|
97
|
+
# @raise [ArgumentError] This exception is raised if the hash contains
|
98
|
+
# values that are not hashes or nils.
|
46
99
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
module ClassMethods
|
51
|
-
# Factory method builds a {Tree::TreeNode} from a +Hash+.
|
52
|
-
#
|
53
|
-
# This method will interpret each key of your +Hash+ as a {Tree::TreeNode}.
|
54
|
-
# Nested hashes are expected and child nodes will be added accordingly. If
|
55
|
-
# a hash key is a single value that value will be used as the name for the
|
56
|
-
# node. If a hash key is an Array, both node name and content will be
|
57
|
-
# populated.
|
58
|
-
#
|
59
|
-
# A leaf element of the tree should be represented as a hash key with
|
60
|
-
# corresponding value +nil+ or +{}+.
|
61
|
-
#
|
62
|
-
# @example
|
63
|
-
# TreeNode.from_hash({:A => {:B => {}, :C => {:D => {}, :E => {}}}})
|
64
|
-
# # would be parsed into the following tree structure:
|
65
|
-
# # A
|
66
|
-
# # / \
|
67
|
-
# # B C
|
68
|
-
# # / \
|
69
|
-
# # D E
|
70
|
-
#
|
71
|
-
# # The same tree would result from this nil-terminated Hash
|
72
|
-
# {:A => {:B => nil, :C => {:D => nil, :E => nil}}}
|
73
|
-
#
|
74
|
-
# # A tree with equivalent structure but with content present for
|
75
|
-
# # nodes A and D could be built from a hash like this:
|
76
|
-
# {[:A, "A content"] => {:B => {},
|
77
|
-
# :C => { [:D, "D content"] => {},
|
78
|
-
# :E => {} }}}
|
79
|
-
#
|
80
|
-
# @author Jen Hamon (http://www.github.com/jhamon)
|
81
|
-
# @param [Hash] hash Hash to build tree from.
|
82
|
-
#
|
83
|
-
# @return [Tree::TreeNode] The {Tree::TreeNode} instance representing the
|
84
|
-
# root of your tree.
|
85
|
-
#
|
86
|
-
# @raise [ArgumentError] This exception is raised if a non-Hash is passed.
|
87
|
-
#
|
88
|
-
# @raise [ArgumentError] This exception is raised if the hash has multiple
|
89
|
-
# top-level elements.
|
90
|
-
#
|
91
|
-
# @raise [ArgumentError] This exception is raised if the hash contains
|
92
|
-
# values that are not hashes or nils.
|
100
|
+
def from_hash(hash)
|
101
|
+
raise ArgumentError, 'Argument must be a type of hash'\
|
102
|
+
unless hash.is_a?(Hash)
|
93
103
|
|
94
|
-
|
95
|
-
|
96
|
-
unless hash.is_a?(Hash)
|
104
|
+
raise ArgumentError, 'Hash must have one top-level element'\
|
105
|
+
if hash.size != 1
|
97
106
|
|
98
|
-
|
99
|
-
if hash.size != 1
|
107
|
+
root, children = hash.first
|
100
108
|
|
101
|
-
|
109
|
+
raise ArgumentError, 'Invalid child. Must be nil or hash.' unless [Hash, NilClass].include?(children.class)
|
102
110
|
|
103
|
-
|
111
|
+
node = new(*root)
|
112
|
+
node.add_from_hash(children) unless children.nil?
|
113
|
+
node
|
114
|
+
end
|
115
|
+
end
|
104
116
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
117
|
+
# Instantiate and insert child nodes from data in a Ruby +Hash+
|
118
|
+
#
|
119
|
+
# This method is used in conjunction with from_hash to provide a
|
120
|
+
# convenient way of building and inserting child nodes present in a Ruby
|
121
|
+
# hashes.
|
122
|
+
#
|
123
|
+
# This method will instantiate a node instance for each top-
|
124
|
+
# level key of the input hash, to be inserted as children of the receiver
|
125
|
+
# instance.
|
126
|
+
#
|
127
|
+
# Nested hashes are expected and further child nodes will be created and
|
128
|
+
# added accordingly. If a hash key is a single value that value will be
|
129
|
+
# used as the name for the node. If a hash key is an Array, both node
|
130
|
+
# name and content will be populated.
|
131
|
+
#
|
132
|
+
# A leaf element of the tree should be represented as a hash key with
|
133
|
+
# corresponding value +nil+ or {}.
|
134
|
+
#
|
135
|
+
# @example
|
136
|
+
# root = Tree::TreeNode.new(:A, "Root content!")
|
137
|
+
# root.add_from_hash({:B => {:D => {}}, [:C, "C content!"] => {}})
|
138
|
+
#
|
139
|
+
# @author Jen Hamon (http://www.github.com/jhamon)
|
140
|
+
# @param [Hash] children The hash of child subtrees.
|
141
|
+
# @raise [ArgumentError] This exception is raised if a non-hash is passed.
|
142
|
+
# @return [Array] Array of child nodes added
|
143
|
+
# @see ClassMethods#from_hash
|
144
|
+
def add_from_hash(children)
|
145
|
+
raise ArgumentError, 'Argument must be a type of hash'\
|
146
|
+
unless children.is_a?(Hash)
|
110
147
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
# This method will instantiate a node instance for each top-
|
118
|
-
# level key of the input hash, to be inserted as children of the receiver
|
119
|
-
# instance.
|
120
|
-
#
|
121
|
-
# Nested hashes are expected and further child nodes will be created and
|
122
|
-
# added accordingly. If a hash key is a single value that value will be
|
123
|
-
# used as the name for the node. If a hash key is an Array, both node
|
124
|
-
# name and content will be populated.
|
125
|
-
#
|
126
|
-
# A leaf element of the tree should be represented as a hash key with
|
127
|
-
# corresponding value +nil+ or {}.
|
128
|
-
#
|
129
|
-
# @example
|
130
|
-
# root = Tree::TreeNode.new(:A, "Root content!")
|
131
|
-
# root.add_from_hash({:B => {:D => {}}, [:C, "C content!"] => {}})
|
132
|
-
#
|
133
|
-
# @author Jen Hamon (http://www.github.com/jhamon)
|
134
|
-
# @param [Hash] children The hash of child subtrees.
|
135
|
-
# @raise [ArgumentError] This exception is raised if a non-hash is passed.
|
136
|
-
# @return [Array] Array of child nodes added
|
137
|
-
# @see ClassMethods#from_hash
|
138
|
-
def add_from_hash(children)
|
139
|
-
raise ArgumentError, 'Argument must be a type of hash'\
|
140
|
-
unless children.is_a?(Hash)
|
148
|
+
child_nodes = []
|
149
|
+
children.each do |child, grandchildren|
|
150
|
+
child_node = self.class.from_hash({ child => grandchildren })
|
151
|
+
child_nodes << child_node
|
152
|
+
self << child_node
|
153
|
+
end
|
141
154
|
|
142
|
-
|
143
|
-
|
144
|
-
child_node = self.class.from_hash({ child => grandchildren })
|
145
|
-
child_nodes << child_node
|
146
|
-
self << child_node
|
147
|
-
end
|
155
|
+
child_nodes
|
156
|
+
end
|
148
157
|
|
149
|
-
|
150
|
-
|
158
|
+
# Convert a node and its subtree into a Ruby hash.
|
159
|
+
#
|
160
|
+
# @example
|
161
|
+
# root = Tree::TreeNode.new(:root, "root content")
|
162
|
+
# root << Tree::TreeNode.new(:child1, "child1 content")
|
163
|
+
# root << Tree::TreeNode.new(:child2, "child2 content")
|
164
|
+
# root.to_h # => {[:root, "root content"] =>
|
165
|
+
# { [:child1, "child1 content"] =>
|
166
|
+
# {}, [:child2, "child2 content"] => {}}}
|
167
|
+
# @author Jen Hamon (http://www.github.com/jhamon)
|
168
|
+
# @return [Hash] Hash representation of tree.
|
169
|
+
def to_h
|
170
|
+
key = content? ? [name, content] : name
|
151
171
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
# root << Tree::TreeNode.new(:child1, "child1 content")
|
157
|
-
# root << Tree::TreeNode.new(:child2, "child2 content")
|
158
|
-
# root.to_h # => {[:root, "root content"] =>
|
159
|
-
# { [:child1, "child1 content"] =>
|
160
|
-
# {}, [:child2, "child2 content"] => {}}}
|
161
|
-
# @author Jen Hamon (http://www.github.com/jhamon)
|
162
|
-
# @return [Hash] Hash representation of tree.
|
163
|
-
def to_h
|
164
|
-
key = has_content? ? [name, content] : name
|
172
|
+
children_hash = {}
|
173
|
+
children do |child|
|
174
|
+
children_hash.merge! child.to_h
|
175
|
+
end
|
165
176
|
|
166
|
-
|
167
|
-
|
168
|
-
children_hash.merge! child.to_h
|
177
|
+
{ key => children_hash }
|
178
|
+
end
|
169
179
|
end
|
170
|
-
|
171
|
-
{ key => children_hash }
|
172
180
|
end
|
173
181
|
end
|