depth 0.1.0 → 0.3.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/README.md +44 -1
- data/lib/depth/actions.rb +11 -3
- data/lib/depth/enumeration/enumerable.rb +18 -18
- data/lib/depth/enumeration/node.rb +4 -0
- data/lib/depth/traverser.rb +2 -2
- data/lib/depth/version.rb +1 -1
- data/spec/depth/actions_spec.rb +25 -0
- data/spec/depth/enumerable_spec.rb +17 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 12186cff293335e8e867ec9c826644c4b175160c
|
4
|
+
data.tar.gz: 1de2bcf3603c3838ae27c95f4b3f4cd3d961ee4b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3d24285ec52b1ac2f878ab29a6287c548794a7e0dfd1e50eb6d4d2e916df996434a404690cb83b58a3ccf36961217843c5e647f76ea4d831749b272ba8c6bd7
|
7
|
+
data.tar.gz: c65350a161b063d0c855a05a58a9bcfe089cf503f9a462f2ec686f00239de91049233f99154216ddcc7813595125a9f9b83c8a4e6f41f0df488ec7ab991d223d
|
data/README.md
CHANGED
@@ -71,6 +71,10 @@ Routes can be defined as an array of keys or indeces:
|
|
71
71
|
]}
|
72
72
|
route = ['$and', 1, '$or', 0, '#otherfeed', 'thing']
|
73
73
|
Depth::ComplexHash.new(hash).find(route) # => []
|
74
|
+
|
75
|
+
# Or with a default
|
76
|
+
Depth::ComplexHash.new(hash).find(%w(not a route), default: 'hello') # => 'hello'
|
77
|
+
|
74
78
|
```
|
75
79
|
|
76
80
|
But there's something cool hidden in the `set` message,
|
@@ -106,6 +110,39 @@ an array, no worries, just say so in the route:
|
|
106
110
|
route = ['$and', 1, '$or', 0, RouteElement.new('#sup', type: :array), 0]
|
107
111
|
```
|
108
112
|
|
113
|
+
Find can also perform the same magic if you set the keyword
|
114
|
+
argument `create` to be true. A default value can also be supplied:
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
hash = { '$and' => [
|
118
|
+
{ '#weather' => { 'something' => [], 'thisguy' => 4 } },
|
119
|
+
{ '$or' => [
|
120
|
+
{ '#otherfeed' => {'thing' => [] } },
|
121
|
+
]}
|
122
|
+
]}
|
123
|
+
route = ['$and', 1, '$or', 0, '#sup', 'thisthing']
|
124
|
+
Depth::ComplexHash.new(hash).find(route, create: true)
|
125
|
+
puts hash.inspect #=>
|
126
|
+
# hash = { '$and' => [
|
127
|
+
# { '#weather' => { 'something' => [], 'thisguy' => 4 } },
|
128
|
+
# { '$or' => [
|
129
|
+
# { '#otherfeed' => {'thing' => [] } },
|
130
|
+
# { '#sup' => { } },
|
131
|
+
# ]}
|
132
|
+
# ]}
|
133
|
+
|
134
|
+
# Or if you supply a default value as well
|
135
|
+
val = Depth::ComplexHash.new(hash).find(route, create: true, default: 'blargle')
|
136
|
+
puts val #=> 'blargle'
|
137
|
+
puts hash.inspect #=>
|
138
|
+
# hash = { '$and' => [
|
139
|
+
# { '#weather' => { 'something' => [], 'thisguy' => 4 } },
|
140
|
+
# { '$or' => [
|
141
|
+
# { '#otherfeed' => {'thing' => [] } },
|
142
|
+
# { '#sup' => { 'thisthing' => 'blargle' } },
|
143
|
+
# ]}
|
144
|
+
# ]}
|
145
|
+
```
|
109
146
|
### Enumeration
|
110
147
|
|
111
148
|
The messages signatures relating to enumeration are:
|
@@ -116,7 +153,7 @@ The messages signatures relating to enumeration are:
|
|
116
153
|
* `map` = yields `key_or_index`, `fragment` and `parent_type`, returns a new complex hash
|
117
154
|
* `map_values` = yields `fragment`, returns a new complex hash
|
118
155
|
* `map_keys` = yields `key_or_index`, returns a new complex hash
|
119
|
-
* `map!`, `map_keys!` and `map_keys_and_values!`, returns
|
156
|
+
* `map!`, `map_keys!` and `map_keys_and_values!`, returns the base complex hash
|
120
157
|
* `reduce(memo)` = yields `memo`, `key` and `fragment`, returns memo
|
121
158
|
* `each_with_object(obj)` = yields `key`, `fragment` and `object`, returns object
|
122
159
|
|
@@ -124,6 +161,12 @@ _Fragment refers to a chunk of the original hash_
|
|
124
161
|
|
125
162
|
These, perhaps, require a bit more explanation:
|
126
163
|
|
164
|
+
_NB_ All of these methods yield an argument at the end
|
165
|
+
which is the route taken to get to this fragment of the hash,
|
166
|
+
I've not detailed the use of it here because it's rarely necessary but
|
167
|
+
it's available in case you have some complex map rules that change
|
168
|
+
based on where you are in the hash.
|
169
|
+
|
127
170
|
#### each
|
128
171
|
|
129
172
|
The staple, and arguably the most important, of all the enumeration methods,
|
data/lib/depth/actions.rb
CHANGED
@@ -14,11 +14,19 @@ module Depth
|
|
14
14
|
object[route.last.key] = value
|
15
15
|
end
|
16
16
|
|
17
|
-
def find(route)
|
17
|
+
def find(route, create: false, default: nil)
|
18
18
|
route = RouteElement.convert_route(route)
|
19
|
-
route.reduce(Traverser.new(base)) { |t, route_el|
|
20
|
-
|
19
|
+
parent = route[0 ... -1].reduce(Traverser.new(base)) { |t, route_el|
|
20
|
+
if create
|
21
|
+
t.next_or_create(route_el.key) { route_el.create }
|
22
|
+
else
|
23
|
+
t.next(route_el.key)
|
24
|
+
end
|
21
25
|
}.object
|
26
|
+
object = parent ? parent[route.last.key] : nil
|
27
|
+
return object unless object.nil?
|
28
|
+
return parent[route.last.key] = default if create && default
|
29
|
+
default
|
22
30
|
end
|
23
31
|
|
24
32
|
def alter(route, key: nil, value: nil)
|
@@ -8,9 +8,9 @@ module Depth
|
|
8
8
|
#:nocov:
|
9
9
|
|
10
10
|
def each_with_object(object, &block)
|
11
|
-
object.tap do |
|
12
|
-
each do |key, fragment|
|
13
|
-
block.call(key, fragment,
|
11
|
+
object.tap do |obj|
|
12
|
+
each do |key, fragment, route|
|
13
|
+
block.call(key, fragment, obj, route)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
@@ -18,11 +18,11 @@ module Depth
|
|
18
18
|
def select(&block)
|
19
19
|
new_q = self.class.new(base.class.new)
|
20
20
|
routes_to_delete = []
|
21
|
-
enumerate do |node|
|
21
|
+
enumerate do |node, route|
|
22
22
|
key = node.parent_key
|
23
23
|
existing = new_q.find(node.route)
|
24
24
|
fragment = existing.nil? ? node.fragment : existing
|
25
|
-
keep = block.call(key, fragment)
|
25
|
+
keep = block.call(key, fragment, route)
|
26
26
|
if keep
|
27
27
|
new_q.alter(node.route, key: key, value: fragment)
|
28
28
|
else
|
@@ -34,12 +34,12 @@ module Depth
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def reject(&block)
|
37
|
-
select{ |key, fragment| !block.call(key, fragment) }
|
37
|
+
select{ |key, fragment, route| !block.call(key, fragment, route) }
|
38
38
|
end
|
39
39
|
|
40
40
|
def reduce(memo, &block)
|
41
|
-
each do |key, fragment|
|
42
|
-
memo = block.call(memo, key, fragment)
|
41
|
+
each do |key, fragment, route|
|
42
|
+
memo = block.call(memo, key, fragment, route)
|
43
43
|
end
|
44
44
|
memo
|
45
45
|
end
|
@@ -60,36 +60,36 @@ module Depth
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def map_keys(&block)
|
63
|
-
map do |key, fragment|
|
64
|
-
[block.call(key), fragment]
|
63
|
+
map do |key, fragment, route|
|
64
|
+
[block.call(key, route), fragment]
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
68
|
def map_values(&block)
|
69
|
-
map do |key, fragment,
|
70
|
-
[key, block.call(fragment)]
|
69
|
+
map do |key, fragment, route|
|
70
|
+
[key, block.call(fragment, route)]
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
74
|
def map(&block)
|
75
|
-
node_map do |node, new_q|
|
75
|
+
node_map do |node, new_q, route|
|
76
76
|
orig_key = node.parent_key
|
77
77
|
existing = new_q.find(node.route)
|
78
78
|
orig_fragment = existing.nil? ? node.fragment : existing
|
79
|
-
block.call(orig_key, orig_fragment)
|
79
|
+
block.call(orig_key, orig_fragment, route)
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
83
|
def each(&block)
|
84
|
-
enumerate { |node| block.call(node.parent_key, node.fragment) }
|
84
|
+
enumerate { |node, route| block.call(node.parent_key, node.fragment, route) }
|
85
85
|
end
|
86
86
|
|
87
87
|
private
|
88
88
|
|
89
89
|
def node_map(&block)
|
90
90
|
new_q = self.class.new(base.class.new)
|
91
|
-
enumerate do |node|
|
92
|
-
key, val = block.call(node, new_q)
|
91
|
+
enumerate do |node, route|
|
92
|
+
key, val = block.call(node, new_q, route)
|
93
93
|
new_q.alter(node.route, key: key, value: val)
|
94
94
|
end
|
95
95
|
new_q
|
@@ -102,7 +102,7 @@ module Depth
|
|
102
102
|
if current.next?
|
103
103
|
current = current.next
|
104
104
|
elsif !current.root?
|
105
|
-
yield(current)
|
105
|
+
yield(current, current.humanized_route)
|
106
106
|
current = current.parent
|
107
107
|
end
|
108
108
|
end while !current.root? || current.next?
|
data/lib/depth/traverser.rb
CHANGED
@@ -9,12 +9,12 @@ module Depth
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def next(key_or_index)
|
12
|
-
return Traverser.new(nil) if object.nil?
|
12
|
+
return Traverser.new(nil) if object.nil?
|
13
13
|
Traverser.new(object[key_or_index])
|
14
14
|
end
|
15
15
|
|
16
16
|
def next_or_create(key_or_index, &block)
|
17
|
-
return Traverser.new(nil) if object.nil?
|
17
|
+
return Traverser.new(nil) if object.nil?
|
18
18
|
object[key_or_index] = block.call if object[key_or_index].nil?
|
19
19
|
Traverser.new(object[key_or_index])
|
20
20
|
end
|
data/lib/depth/version.rb
CHANGED
data/spec/depth/actions_spec.rb
CHANGED
@@ -102,6 +102,31 @@ module Depth
|
|
102
102
|
end
|
103
103
|
|
104
104
|
describe '#find' do
|
105
|
+
context 'with create true' do
|
106
|
+
it 'should create the route if it needs to' do
|
107
|
+
route = [['$yo', :array], 0, '$thing']
|
108
|
+
expect {
|
109
|
+
subject.find(route, create: true)
|
110
|
+
}.to change { subject.base['$yo'] }.to( [{}] )
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'with a default value' do
|
114
|
+
it 'should create the route and value it needs to' do
|
115
|
+
route = [['$yo', :array], 0, '$thing']
|
116
|
+
expect {
|
117
|
+
subject.find(route, create: true, default: 4)
|
118
|
+
}.to change { subject.base['$yo'] }.to( [{'$thing' => 4}] )
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context 'with a default value and a missing route' do
|
124
|
+
it 'should return the default' do
|
125
|
+
route = ['$yo', 0, '$thing']
|
126
|
+
expect(subject.find(route, default: 'blah')).to eq 'blah'
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
105
130
|
it 'should let me find an existing value' do
|
106
131
|
route = [['$and', :array], [0, :hash],
|
107
132
|
['#weather', :hash], ['something', :array]]
|
@@ -157,7 +157,7 @@ module Depth::Enumeration
|
|
157
157
|
|
158
158
|
context 'with alteration' do
|
159
159
|
let(:result) do
|
160
|
-
subject.map do |k, v|
|
160
|
+
subject.map do |k, v, r|
|
161
161
|
next [k, v] unless k.is_a?(String)
|
162
162
|
["#{k}Altered", 'redacted']
|
163
163
|
end
|
@@ -218,6 +218,22 @@ module Depth::Enumeration
|
|
218
218
|
end
|
219
219
|
|
220
220
|
describe '#each' do
|
221
|
+
it 'should keep track of where we are' do
|
222
|
+
routes = []
|
223
|
+
subject.each do |_, _, route|
|
224
|
+
routes << route
|
225
|
+
end
|
226
|
+
|
227
|
+
expected = [
|
228
|
+
["$and", 0, "#weather", "something"], ["$and", 0, "#weather"],
|
229
|
+
["$and", 0], ["$and", 1, "$or", 0, "#otherfeed", "thing"],
|
230
|
+
["$and", 1, "$or", 0, "#otherfeed"], ["$and", 1, "$or", 0],
|
231
|
+
["$and", 1, "$or"], ["$and", 1], ["$and"]
|
232
|
+
]
|
233
|
+
|
234
|
+
expect(routes).to eq(expected)
|
235
|
+
end
|
236
|
+
|
221
237
|
it 'should sort through all keys and values' do
|
222
238
|
enumerated = []
|
223
239
|
subject.each do |key, fragment|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: depth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Max
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|