order_tree 0.0.3 → 0.0.4

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.
@@ -20,7 +20,7 @@ module OrderTree
20
20
  # @param [OrderTree] OrderTree - the root tree object.
21
21
  # @note The order of insertion might not be what you would expect for multi-
22
22
  # level hash literals. The most deeply nested values will be inserted FIRST.
23
- def initialize(constructor = {}, root = nil)
23
+ def initialize(constructor = {}, root = nil)
24
24
  @_delegate_hash = {}
25
25
  self.root = root || self
26
26
  constructor.each_with_object(self) do |(k,v),memo|
@@ -68,7 +68,7 @@ module OrderTree
68
68
  def each_pair
69
69
  return enum_for(:each_pair) unless block_given?
70
70
  self.each do |c|
71
- yield c.path, c.orig
71
+ yield c.path.dup, c.orig
72
72
  end
73
73
  end
74
74
 
@@ -91,7 +91,7 @@ module OrderTree
91
91
  def each_path
92
92
  return enum_for(:each_path) unless block_given?
93
93
  self.each do |v|
94
- yield v.path
94
+ yield v.path.dup
95
95
  end
96
96
  end
97
97
 
@@ -197,6 +197,10 @@ module OrderTree
197
197
  _delegate_hash.inspect
198
198
  end
199
199
 
200
+ def pretty_print(pp)
201
+ _delegate_hash.pretty_print(pp)
202
+ end
203
+
200
204
  # @param [OrderTree] other
201
205
  # @return [true] if self and other do not share all leaves or were inserted in a different order
202
206
  def != other
@@ -258,7 +262,24 @@ module OrderTree
258
262
  t = self.at *paths
259
263
  t.orig
260
264
  end
261
-
265
+
266
+ # Returns true if the given path points to a non-default object
267
+ # @param [Array] path to check for
268
+ # @return [Boolean] true if path is not the default object
269
+ def has_path? *paths
270
+ t = self
271
+ penum = paths.each
272
+ loop do
273
+ current_path = penum.next
274
+ dh = t.__send__ :_delegate_hash
275
+ return false unless dh.has_key? current_path
276
+ t = dh[current_path]
277
+ end
278
+ true
279
+ rescue NoMethodError => e
280
+ return false if e.name == :_delegate_hash
281
+ end
282
+ alias :has_key? :has_path?
262
283
 
263
284
  # @private
264
285
  def _find_delegate_hash *paths
@@ -280,12 +301,37 @@ module OrderTree
280
301
  end
281
302
  private :_find_delegate_hash
282
303
 
304
+ def _insert_ordered_node branch, path, value
305
+ if branch.has_key? path # i am overwriting a path
306
+ branch[path].remove
307
+ end
308
+ branch[path] = OrderTreeNode.new(value, self)
309
+ branch[path].prev = root.last if root.last
310
+ root.last.next = branch[path] if root.last
311
+ root.last = branch[path]
312
+ end
313
+ private :_insert_ordered_node
314
+
283
315
  # Prune branch from the tree
284
316
  # @param [Array] path
285
317
  def delete *paths
286
- under = _find_delegate_hash *paths
287
- if under.has_key? paths.last
288
- under[paths.last].remove
318
+ branch = _find_delegate_hash *paths
319
+ if branch.has_key? paths.last
320
+ branch[paths.last].remove
321
+ end
322
+ end
323
+
324
+ # The nodes of immediate branches under path
325
+ # @param [Array] path
326
+ # @return [Enumerator] enumeration of the nodes under the reciever, in order
327
+ def branches *path
328
+ return enum_for(:branches, *path) unless block_given?
329
+ self.each_pair do |k,v|
330
+ if k.slice(0, path.size) == path
331
+ sub_key = k - k.slice(0,path.size)
332
+ v = proxy?(v) ? v.deproxy : v
333
+ yield sub_key[0], v unless sub_key.size != 1
334
+ end
289
335
  end
290
336
  end
291
337
 
@@ -293,27 +339,23 @@ module OrderTree
293
339
  # @param [Array] path
294
340
  # @param [Object] value
295
341
  def []= *paths, value
296
- under = _find_delegate_hash *paths
297
-
298
- if value.kind_of? Hash or value.kind_of? OrderTree
342
+ branch = _find_delegate_hash *paths
343
+
344
+ if value.kind_of? Hash or value.kind_of? OrderTree and not @no_expand_hash
299
345
  value = OrderTree.new(value, @root)
300
346
  value.default= self.root.default
301
347
  end
302
-
303
- if under.has_key? paths.last # i am overwriting a path
304
- under[paths.last].remove
305
- end
306
-
307
- under[paths.last] = OrderTreeNode.new(value, self)
308
- under[paths.last].prev = root.last if root.last
309
- root.last.next = under[paths.last] if root.last
310
- root.last = under[paths.last]
311
-
312
- #@order.push under[paths.last]
313
-
314
- #puts "insertion of '#{value}' in #{self.to_s} -> #{@order.to_s} (id #{under[paths.last].unique_id})"
348
+ _insert_ordered_node branch, paths.last, value
349
+ value
350
+ end
351
+
352
+ # Stores the value at path without expanding value into an OrderTree if it is a hash
353
+ # @param [Array] path
354
+ # @param [Object] value
355
+ def store *paths, value
356
+ branch = _find_delegate_hash *paths
357
+ _insert_ordered_node branch, paths.last, value
315
358
  value
316
359
  end
317
- alias :store :[]=
318
360
  end
319
361
  end
@@ -44,6 +44,15 @@ module OrderTree
44
44
  self
45
45
  end
46
46
 
47
+ def deproxy
48
+ orig = self.orig.respond_to?(:dup) ? self.orig.dup : self.orig
49
+ if orig.respond_to? :each
50
+ orig.each.map! { |i| proxy?(i) ? i.deproxy : i }
51
+ end
52
+ orig
53
+ end
54
+
55
+
47
56
  def before other
48
57
  (self <=> other) == -1 ? true : false
49
58
  end
@@ -72,6 +72,10 @@ module OrderTree
72
72
  @obj
73
73
  end
74
74
 
75
+ def deproxy
76
+ @obj
77
+ end
78
+
75
79
  # Dispatches methods calls to proxy target
76
80
  def method_missing(method, *args, &block)
77
81
  @obj.__send__ method, *args, &block
@@ -84,6 +88,7 @@ module OrderTree
84
88
 
85
89
  # @private
86
90
  def == arg
91
+ return true if @obj.nil? and arg.nil?
87
92
  @obj == arg
88
93
  end
89
94
 
@@ -1,3 +1,3 @@
1
1
  module OrderTree
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -22,6 +22,11 @@ describe OrderTree::UniqueProxy do
22
22
  (a.orig.equal? b.orig).should eq true
23
23
  end
24
24
 
25
+ it "unique proxy over nil should be == to itself" do
26
+ #proxy objects over nil do not respond correctly to "should"
27
+ (proxy(nil) == proxy(nil)).should be_true
28
+ end
29
+
25
30
  it "can retrieve the unique id" do
26
31
  a = OrderTree::UniqueProxy.new(4)
27
32
  b = OrderTree::UniqueProxy.new(4)
@@ -115,6 +120,14 @@ describe OrderTree::OrderTree do
115
120
  end
116
121
  end
117
122
 
123
+ it "can tell you whether a path exists" do
124
+ ot = OrderTree::OrderTree.new(@testhash)
125
+ (ot.has_key? :from, :a, :c).should be_true
126
+ (ot.has_key? :from, :to, :c).should be_false
127
+ (ot.has_key? :from).should be_true
128
+ (ot.has_key? :from, :a, :c, :d).should be_false
129
+ end
130
+
118
131
  it "can set based on path or nest" do
119
132
  ot = OrderTree::OrderTree.new(@testhash)
120
133
  ot2 = OrderTree::OrderTree.new(@testhash_insertion)
@@ -126,6 +139,23 @@ describe OrderTree::OrderTree do
126
139
  end
127
140
  end
128
141
 
142
+ it "can store hashes without expanding them by accessing the underlying hash" do
143
+ ot = OrderTree::OrderTree.new({:first => "a"})
144
+ ot[:first] = {:a => 2}
145
+ ot.min.path.should eq [:first, :a] #this is important later!
146
+
147
+ ot.max.path.should eq [:first] #because it will reinsier :first as an order_tree
148
+ ot[:first][:b] = 3
149
+ ot.max.path.should eq [:first, :b] #because first is an OrderTree
150
+ lambda { ot[:first, :c, :d] = 3 }.should raise_error NoMethodError # because it can't reifiy tree leaves on create
151
+ ot[:first, :c] = { :d => 3}
152
+ ot.max.path.should eq [:first, :c]
153
+ ot.max.prev.path.should eq [:first, :c, :d] #because a hash was added with tree access
154
+ ot.store(:first, :c, { :e => 5})
155
+ ot.max.prev.path.should eq [:first,:c ,:d]
156
+ (ot[*ot.max.prev.path] == ot.default.orig).should be_true
157
+ end
158
+
129
159
  it "remember the order" do
130
160
  ot = OrderTree::OrderTree.new(@testhash)
131
161
  ot2 = OrderTree::OrderTree.new(@testhash_insertion)
@@ -211,6 +241,7 @@ describe OrderTree::OrderTree do
211
241
  ot.each_path.to_a.first.should eq second_path
212
242
  end
213
243
 
244
+
214
245
  it "does == comparison" do
215
246
  ot = OrderTree::OrderTree.new @testhash
216
247
  ot2 = OrderTree::OrderTree.new @testhash
@@ -296,6 +327,15 @@ describe OrderTree::OrderTree do
296
327
  ot[:to, :to_to].should eq "bob"
297
328
  end
298
329
 
330
+ it "can get the branches for node" do
331
+ ot = OrderTree::OrderTree.new @testhash
332
+ ot.branches(:from, :a).to_a.should eq [[:b,4], [:c,4]]
333
+ # it actually returns the ordertree (as it should) and not the underlying
334
+ # has, but for the sake of simplicity comare the string representations
335
+ ot.branches(:from).to_a.to_s.should eq "[[:a, {:b=>4, :c=>4}]]"
336
+ ot.branches.to_a.to_s.should eq "[[:from, {:a=>{:b=>4, :c=>4}}], [:to, {:d=>4, :e=>4, :to_to=>{:f=>5, :g=>6, :h=>7}}]]"
337
+ end
338
+
299
339
  it "can find the path for a node object" do
300
340
  ot = OrderTree::OrderTree.new @testhash
301
341
  lambda do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: order_tree
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,12 +9,12 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-07-26 00:00:00.000000000 -05:00
12
+ date: 2011-10-03 00:00:00.000000000 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
17
- requirement: &3691050 !ruby/object:Gem::Requirement
17
+ requirement: &10085620 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: '0'
23
23
  type: :development
24
24
  prerelease: false
25
- version_requirements: *3691050
25
+ version_requirements: *10085620
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: simplecov
28
- requirement: &3690830 !ruby/object:Gem::Requirement
28
+ requirement: &10085410 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
- version_requirements: *3690830
36
+ version_requirements: *10085410
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: ruby-prof
39
- requirement: &3690610 !ruby/object:Gem::Requirement
39
+ requirement: &10085200 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,10 +44,10 @@ dependencies:
44
44
  version: '0'
45
45
  type: :development
46
46
  prerelease: false
47
- version_requirements: *3690610
47
+ version_requirements: *10085200
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: ruby-debug19
50
- requirement: &3690400 !ruby/object:Gem::Requirement
50
+ requirement: &10084990 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
53
  - - ! '>='
@@ -55,7 +55,7 @@ dependencies:
55
55
  version: '0'
56
56
  type: :development
57
57
  prerelease: false
58
- version_requirements: *3690400
58
+ version_requirements: *10084990
59
59
  description: Use OrderTree when you need both insertion order access and nested hash
60
60
  path style access
61
61
  email: