hash-tree 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/lib/hash-tree.rb +32 -0
  3. data/spec/hash-tree_spec.rb +94 -1
  4. metadata +52 -46
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c92972764199548bb71f2e92dbe36e12664e5b21
4
+ data.tar.gz: ad4c922293c7d57e916ec3c878f83a3425cafd64
5
+ SHA512:
6
+ metadata.gz: b9fc07836a7a8937e1dd0dfe691b3ec574240ac0ada34efc425ca072bf5e8dc46a0fd84f77af93ac8b39081f8f1a07c598b0f36efe4a40d6c83ac8f78b9833ec
7
+ data.tar.gz: c3628f1a3d83242e4e52ebc7a0d22f53f296437f16141e6104dd84f3080163ebb8cd45599093c8a21d5526744ec1abe3c17e15b82771f4d5c5a9af351c7f1bac
@@ -99,6 +99,38 @@ class HashTree
99
99
  end
100
100
  end
101
101
 
102
+ # Takes a path (keys separated by dots) and yield an hash of the parents of all level (ascendants) up to the root, along with the value of the path.
103
+ def each_node(path, options={}, &block)
104
+ options = { :hash => @hash, :key_path => [], :parents => {} }.merge(options)
105
+ return unless path && !path.empty?
106
+
107
+ all_keys = path.split('.')
108
+ keys = all_keys[options[:key_path].size..-1]
109
+ key = keys.shift
110
+ key_path = [options[:key_path], key].flatten
111
+ key_path_string = key_path.join('.')
112
+ value = options[:hash][key]
113
+
114
+ if value
115
+ parents = options[:parents].merge(Hash[key_path_string, options[:hash]])
116
+
117
+ # Go no further?
118
+ if (key_path == all_keys)
119
+ yield parents, value
120
+ else
121
+ if value.kind_of? Array
122
+ value.each do |item|
123
+ if item.kind_of? Hash
124
+ each_node(path, {:hash => item, :key_path => key_path, :parents => parents}, &block)
125
+ end
126
+ end
127
+ elsif value.kind_of? Hash
128
+ each_node(path, {:hash => value, :key_path => key_path, :parents => parents}, &block)
129
+ end
130
+ end
131
+ end
132
+ end
133
+
102
134
  def empty?
103
135
  @hash.empty?
104
136
  end
@@ -95,8 +95,101 @@ describe HashTree do
95
95
  end
96
96
  end
97
97
 
98
+ # nodes are considered nodes when no more hash can be found in the child
98
99
  describe "#each" do
99
- pending 'TOTEST'
100
+ subject do
101
+ HashTree.new({ 'n1' => [
102
+ { 'l11' => '' },
103
+ { 'l12' => '', 'n11' => ['l111', 'l112'] },
104
+ { 'l13' => '', 'n12' => [{'l121' => '', 'l122' => ''}, {}] },
105
+ { 'n13' => {
106
+ 'n131' => {
107
+ 'n1311' => ['l311'], 'n1312' => {'l31121' => '', 'n13121' => ['l3121']}
108
+ }
109
+ }
110
+ }
111
+ ]})
112
+ end
113
+
114
+ it { expect { |b| subject.each(&b) }.to yield_successive_args(
115
+ [{"l11"=>""}, "l11", "", "n1.l11"],
116
+ [{"l12"=>"", "n11"=>["l111", "l112"]}, "l12", "", "n1.l12"],
117
+ [{"l12"=>"", "n11"=>["l111", "l112"]}, "n11", "l111", "n1.n11"],
118
+ [{"l12"=>"", "n11"=>["l111", "l112"]}, "n11", "l112", "n1.n11"],
119
+ [{"l13"=>"", "n12"=>[{"l121"=>"", "l122"=>""}, {}]}, "l13", "", "n1.l13"],
120
+ [{"l121"=>"", "l122"=>""}, "l121", "", "n1.n12.l121"],
121
+ [{"l121"=>"", "l122"=>""}, "l122", "", "n1.n12.l122"],
122
+ [{"n1311"=>["l311"], "n1312"=>{"l31121"=>"", "n13121"=>["l3121"]}}, "n1311", "l311", "n1.n13.n131.n1311"],
123
+ [{"l31121"=>"", "n13121"=>["l3121"]}, "l31121", "", "n1.n13.n131.n1312.l31121"],
124
+ [{"l31121"=>"", "n13121"=>["l3121"]}, "n13121", "l3121", "n1.n13.n131.n1312.n13121"]
125
+ )}
126
+ end
127
+
128
+ describe "#each_node" do
129
+ let!(:first_a1) { { 'a11' => 'a111' } }
130
+ let!(:second_a1) { { 'a11' => 'a112', 'b11' => ['b111', 'b1112'] } }
131
+
132
+ let!(:third_a1_first_b11) { {'b111' => 'b31111', 'b112' => 'b31112'} }
133
+ let!(:third_a1_second_b11) { {'b111' => 'b31113'} }
134
+ let!(:third_a1) { { 'a11' => 'a113', 'b11' => [third_a1_first_b11, third_a1_second_b11] } }
135
+
136
+ let!(:fourth_a1_first_b11) { {'b111' => 'b41111', 'b112' => 'b41112'} }
137
+ let!(:fourth_a1) { { 'a11' => 'a114', 'b11' => [fourth_a1_first_b11, {}, ['b112'], 'b112', 5] } }
138
+
139
+ let!(:a1) { [first_a1, second_a1, third_a1, fourth_a1] }
140
+ let!(:first_b1111) { { 'b1111' => 'b11111' } }
141
+ let!(:second_b1111) { { 'b1111' => 'b11112' } }
142
+ let!(:b11) { { 'b111' => [first_b1111, second_b1111] } }
143
+ let!(:b1) { { 'b11' => b11 } }
144
+
145
+ let!(:tree) { { 'a1' => a1, 'b1' => b1 } }
146
+
147
+ subject { HashTree.new(tree) }
148
+
149
+ it { expect { |b| subject.each_node(nil, &b) }.to_not yield_control }
150
+ it { expect { |b| subject.each_node('', &b) }.to_not yield_control }
151
+ it { expect { |b| subject.each_node('doesnotexist', &b) }.to_not yield_control }
152
+ it { expect { |b| subject.each_node('does.not.exist', &b) }.to_not yield_control }
153
+ it { expect { |b| subject.each_node('a1.doesnotexist', &b) }.to_not yield_control }
154
+
155
+ # a node is not a leaf
156
+ it { expect { |b| subject.each_node('a1.a11.a111', &b) }.to_not yield_control }
157
+
158
+
159
+ it { expect { |b| subject.each_node('a1', &b) }.to yield_successive_args(
160
+ [{'a1' => tree}, a1]
161
+ )}
162
+
163
+ it { expect { |b| subject.each_node('a1.a11', &b) }.to yield_successive_args(
164
+ [{'a1' => tree, 'a1.a11' => first_a1}, 'a111'],
165
+ [{'a1' => tree, 'a1.a11' => second_a1}, 'a112'],
166
+ [{'a1' => tree, 'a1.a11' => third_a1}, 'a113'],
167
+ [{'a1' => tree, 'a1.a11' => fourth_a1}, 'a114']
168
+ )}
169
+
170
+ it { expect { |b| subject.each_node('a1.b11', &b) }.to yield_successive_args(
171
+ [{'a1' => tree, 'a1.b11' => second_a1}, ['b111', 'b1112']],
172
+ [{'a1' => tree, 'a1.b11' => third_a1}, [third_a1_first_b11, third_a1_second_b11]],
173
+ [{'a1' => tree, 'a1.b11' => fourth_a1}, [fourth_a1_first_b11, {}, ['b112'], 'b112', 5]]
174
+ )}
175
+
176
+ it { expect { |b| subject.each_node('a1.b11.b111', &b) }.to yield_successive_args(
177
+ [{'a1' => tree, 'a1.b11' => third_a1, 'a1.b11.b111' => third_a1_first_b11}, 'b31111'],
178
+ [{'a1' => tree, 'a1.b11' => third_a1, 'a1.b11.b111' => third_a1_second_b11}, 'b31113'],
179
+ [{'a1' => tree, 'a1.b11' => fourth_a1, 'a1.b11.b111' => fourth_a1_first_b11}, 'b41111']
180
+ )}
181
+
182
+ it { expect { |b| subject.each_node('b1', &b) }.to yield_successive_args(
183
+ [{'b1' => tree}, b1]
184
+ )}
185
+
186
+ it { expect { |b| subject.each_node('b1.b11', &b) }.to yield_successive_args(
187
+ [{'b1' => tree, 'b1.b11' => b1}, b11]
188
+ )}
189
+
190
+ it { expect { |b| subject.each_node('b1.b11.b111', &b) }.to yield_successive_args(
191
+ [{'b1' => tree, 'b1.b11' => b1, 'b1.b11.b111' => b11}, [first_b1111, second_b1111]]
192
+ )}
100
193
  end
101
194
 
102
195
  describe "#empty?" do
metadata CHANGED
@@ -1,93 +1,99 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hash-tree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
5
- prerelease:
4
+ version: 0.0.3
6
5
  platform: ruby
7
6
  authors:
8
7
  - Sebastien Rosa
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-04-16 00:00:00.000000000 Z
11
+ date: 2014-04-07 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: json
16
- requirement: &2152834740 !ruby/object:Gem::Requirement
17
- none: false
15
+ requirement: !ruby/object:Gem::Requirement
18
16
  requirements:
19
- - - ! '>='
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
19
  version: 1.5.0
22
20
  type: :runtime
23
21
  prerelease: false
24
- version_requirements: *2152834740
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 1.5.0
25
27
  - !ruby/object:Gem::Dependency
26
28
  name: ya2yaml
27
- requirement: &2152834220 !ruby/object:Gem::Requirement
28
- none: false
29
+ requirement: !ruby/object:Gem::Requirement
29
30
  requirements:
30
- - - ! '>='
31
+ - - ">="
31
32
  - !ruby/object:Gem::Version
32
33
  version: '0.30'
33
34
  type: :runtime
34
35
  prerelease: false
35
- version_requirements: *2152834220
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0.30'
36
41
  - !ruby/object:Gem::Dependency
37
42
  name: nori
38
- requirement: &2152833680 !ruby/object:Gem::Requirement
39
- none: false
43
+ requirement: !ruby/object:Gem::Requirement
40
44
  requirements:
41
- - - ! '>='
45
+ - - "~>"
42
46
  - !ruby/object:Gem::Version
43
47
  version: 1.1.0
44
48
  type: :runtime
45
49
  prerelease: false
46
- version_requirements: *2152833680
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 1.1.0
47
55
  - !ruby/object:Gem::Dependency
48
56
  name: rake
49
- requirement: &2152832920 !ruby/object:Gem::Requirement
50
- none: false
57
+ requirement: !ruby/object:Gem::Requirement
51
58
  requirements:
52
- - - ! '>='
59
+ - - ">="
53
60
  - !ruby/object:Gem::Version
54
61
  version: 0.8.7
55
62
  type: :development
56
63
  prerelease: false
57
- version_requirements: *2152832920
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 0.8.7
58
69
  - !ruby/object:Gem::Dependency
59
70
  name: rspec
60
- requirement: &2152831900 !ruby/object:Gem::Requirement
61
- none: false
71
+ requirement: !ruby/object:Gem::Requirement
62
72
  requirements:
63
- - - ! '>='
73
+ - - ">="
64
74
  - !ruby/object:Gem::Version
65
75
  version: '2.0'
66
76
  type: :development
67
77
  prerelease: false
68
- version_requirements: *2152831900
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '2.0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rspec-aspic
71
- requirement: &2152830840 !ruby/object:Gem::Requirement
72
- none: false
85
+ requirement: !ruby/object:Gem::Requirement
73
86
  requirements:
74
- - - ! '>='
87
+ - - ">="
75
88
  - !ruby/object:Gem::Version
76
89
  version: 0.0.2
77
90
  type: :development
78
91
  prerelease: false
79
- version_requirements: *2152830840
80
- - !ruby/object:Gem::Dependency
81
- name: rspec-compact-doc-formatter
82
- requirement: &2152830140 !ruby/object:Gem::Requirement
83
- none: false
92
+ version_requirements: !ruby/object:Gem::Requirement
84
93
  requirements:
85
- - - ! '>='
94
+ - - ">="
86
95
  - !ruby/object:Gem::Version
87
- version: 0.0.3
88
- type: :development
89
- prerelease: false
90
- version_requirements: *2152830140
96
+ version: 0.0.2
91
97
  description: HashTree help you to work with nested hashes and arrays.
92
98
  email:
93
99
  - sebastien@demarque.com
@@ -97,6 +103,10 @@ extra_rdoc_files:
97
103
  - LICENSE
98
104
  - README.md
99
105
  files:
106
+ - Gemfile
107
+ - LICENSE
108
+ - README.md
109
+ - Rakefile
100
110
  - lib/hash-tree.rb
101
111
  - spec/fixtures/book.json
102
112
  - spec/fixtures/books.json
@@ -105,33 +115,29 @@ files:
105
115
  - spec/hash-tree_spec.rb
106
116
  - spec/spec_helper.rb
107
117
  - spec/support/application_helpers.rb
108
- - LICENSE
109
- - README.md
110
- - Rakefile
111
- - Gemfile
112
118
  homepage: https://github.com/demarque/hash-tree
113
119
  licenses:
114
120
  - MIT
121
+ metadata: {}
115
122
  post_install_message:
116
123
  rdoc_options: []
117
124
  require_paths:
118
125
  - lib
119
126
  required_ruby_version: !ruby/object:Gem::Requirement
120
- none: false
121
127
  requirements:
122
- - - ! '>='
128
+ - - ">="
123
129
  - !ruby/object:Gem::Version
124
130
  version: '0'
125
131
  required_rubygems_version: !ruby/object:Gem::Requirement
126
- none: false
127
132
  requirements:
128
- - - ! '>='
133
+ - - ">="
129
134
  - !ruby/object:Gem::Version
130
135
  version: '0'
131
136
  requirements: []
132
137
  rubyforge_project: hash-tree
133
- rubygems_version: 1.8.17
138
+ rubygems_version: 2.2.1
134
139
  signing_key:
135
- specification_version: 3
140
+ specification_version: 4
136
141
  summary: Manage nested hash
137
142
  test_files: []
143
+ has_rdoc: