rubytree 1.0.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|