order_tree 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: