depth 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 12186cff293335e8e867ec9c826644c4b175160c
4
- data.tar.gz: 1de2bcf3603c3838ae27c95f4b3f4cd3d961ee4b
3
+ metadata.gz: 85d067842e7799d193a25834e13a66d7b8fd7375
4
+ data.tar.gz: e6af288638c9e95b1a9e3d3fd9a245a05ce17320
5
5
  SHA512:
6
- metadata.gz: a3d24285ec52b1ac2f878ab29a6287c548794a7e0dfd1e50eb6d4d2e916df996434a404690cb83b58a3ccf36961217843c5e647f76ea4d831749b272ba8c6bd7
7
- data.tar.gz: c65350a161b063d0c855a05a58a9bcfe089cf503f9a462f2ec686f00239de91049233f99154216ddcc7813595125a9f9b83c8a4e6f41f0df488ec7ab991d223d
6
+ metadata.gz: 207ae9111a988453a18d33b25c5ba1d70e0249d655874377de02d4f82b6b30b86b9b57b3778a03052b20b828b0f1bd8f859dd601a765937a5d4dd6b4ac3deba8
7
+ data.tar.gz: 012ac2126a5aa29cacf5806fef20cc0686378715b708c5decdcf9d57c975ba78b0c90869449476ef94d52e0486721caef036c29eff93f7c17d10b3ef0a121c6c
@@ -4,28 +4,55 @@ module Depth
4
4
  def base
5
5
  raise NoMethodError.new('should be overridden')
6
6
  end
7
+
8
+ def next_proc
9
+ raise NoMethodError.new('should be overridden')
10
+ end
11
+
12
+ def creation_proc
13
+ raise NoMethodError.new('should be overridden')
14
+ end
15
+
16
+ def key_transformer
17
+ raise NoMethodError.new('should be overridden')
18
+ end
7
19
  #:nocov:
8
20
 
9
21
  def set(route, value)
10
22
  route = RouteElement.convert_route(route)
11
- object = route[0 ... -1].reduce(Traverser.new(base)) { |t, route_el|
23
+ base_traverser = Traverser.new(
24
+ base, next_proc: next_proc,
25
+ creation_proc: creation_proc,
26
+ key_transformer: key_transformer
27
+ )
28
+ object = route[0 ... -1].reduce(base_traverser) { |t, route_el|
12
29
  t.next_or_create(route_el.key) { route_el.create }
13
30
  }.object
14
- object[route.last.key] = value
31
+ original_key = route.last.key
32
+ transformed_key = key_transformer.call(object, route.last.key)
33
+ creation_proc.call(object, transformed_key, value, original_key)
15
34
  end
16
35
 
17
36
  def find(route, create: false, default: nil)
37
+ return self if route.empty?
18
38
  route = RouteElement.convert_route(route)
19
- parent = route[0 ... -1].reduce(Traverser.new(base)) { |t, route_el|
39
+ base_traverser = Traverser.new(
40
+ base, next_proc: next_proc,
41
+ creation_proc: creation_proc,
42
+ key_transformer: key_transformer
43
+ )
44
+ parent = route[0 ... -1].reduce(base_traverser) { |t, route_el|
20
45
  if create
21
46
  t.next_or_create(route_el.key) { route_el.create }
22
47
  else
23
48
  t.next(route_el.key)
24
49
  end
25
50
  }.object
26
- object = parent ? parent[route.last.key] : nil
51
+ original_key = route.last.key
52
+ transformed_key = key_transformer.call(parent, route.last.key)
53
+ object = parent ? next_proc.call(parent, transformed_key, original_key) : nil
27
54
  return object unless object.nil?
28
- return parent[route.last.key] = default if create && default
55
+ return creation_proc.call(parent, transformed_key, default, original_key) if create && default
29
56
  default
30
57
  end
31
58
 
@@ -34,7 +61,8 @@ module Depth
34
61
  route = RouteElement.convert_route(route)
35
62
  value = find(route) unless value
36
63
  new_route = (route[0 ... -1] << RouteElement.convert(key))
37
- set(new_route, value) # ensure it exists
64
+ # ensure it exists
65
+ set(new_route, value)
38
66
  old_key = route.last.key
39
67
  return unless old_key != key
40
68
  delete(route)
@@ -42,13 +70,19 @@ module Depth
42
70
 
43
71
  def delete(route)
44
72
  route = RouteElement.convert_route(route)
45
- traverser = route[0...-1].reduce(Traverser.new(base)) do |t, route_el|
73
+ base_traverser = Traverser.new(
74
+ base, next_proc: next_proc,
75
+ creation_proc: creation_proc,
76
+ key_transformer: key_transformer
77
+ )
78
+ traverser = route[0...-1].reduce(base_traverser) do |t, route_el|
46
79
  t.next(route_el.key)
47
80
  end
81
+ last_key = key_transformer.call(traverser.object, route.last.key)
48
82
  if traverser.array?
49
- traverser.object.delete_at(route.last.key)
83
+ traverser.object.delete_at(last_key)
50
84
  elsif traverser.hash?
51
- traverser.object.delete(route.last.key)
85
+ traverser.object.delete(last_key)
52
86
  end
53
87
  end
54
88
  end
@@ -2,10 +2,19 @@ module Depth
2
2
  class ComplexHash
3
3
  include Depth::Actions
4
4
  include Depth::Enumeration::Enumerable
5
- attr_reader :base
5
+ DEFAULT_KEY_TRANSFORMER = proc { |obj, key| key }
6
+ DEFAULT_NEXT_PROC = proc { |obj, key| obj[key] }
7
+ DEFAULT_CREATION_PROC = proc { |obj, key, val| obj[key] = val }
8
+ attr_reader :base, :next_proc, :creation_proc, :key_transformer
6
9
  alias_method :to_h, :base
7
- def initialize(base = {})
10
+ def initialize(base = {},
11
+ key_transformer: DEFAULT_KEY_TRANSFORMER,
12
+ next_proc: DEFAULT_NEXT_PROC,
13
+ creation_proc: DEFAULT_CREATION_PROC)
8
14
  @base = base
15
+ @next_proc = next_proc
16
+ @creation_proc = creation_proc
17
+ @key_transformer = key_transformer
9
18
  end
10
19
  end
11
20
  end
@@ -1,5 +1,17 @@
1
1
  module Depth
2
- class Traverser < Struct.new(:object)
2
+ class Traverser
3
+
4
+ attr_reader :object
5
+
6
+ def initialize(object,
7
+ key_transformer:,
8
+ next_proc:, creation_proc:)
9
+ @object = object
10
+ @next_proc = next_proc
11
+ @creation_proc = creation_proc
12
+ @key_transformer = key_transformer
13
+ end
14
+
3
15
  def array?
4
16
  object.is_a?(Array)
5
17
  end
@@ -9,14 +21,43 @@ module Depth
9
21
  end
10
22
 
11
23
  def next(key_or_index)
12
- return Traverser.new(nil) if object.nil?
13
- Traverser.new(object[key_or_index])
24
+ original_key = key_or_index
25
+ key_or_index = key_transformer.call(object, key_or_index)
26
+ next_object = if object.nil?
27
+ nil
28
+ else
29
+ next_proc.call(object, key_or_index, original_key)
30
+ end
31
+
32
+ Traverser.new(
33
+ next_object,
34
+ key_transformer: key_transformer,
35
+ next_proc: next_proc,
36
+ creation_proc: creation_proc
37
+ )
14
38
  end
15
39
 
16
40
  def next_or_create(key_or_index, &block)
17
- return Traverser.new(nil) if object.nil?
18
- object[key_or_index] = block.call if object[key_or_index].nil?
19
- Traverser.new(object[key_or_index])
41
+ original_key = key_or_index
42
+ key_or_index = key_transformer.call(object, key_or_index)
43
+ return Traverser.new(
44
+ nil,
45
+ key_transformer: key_transformer,
46
+ next_proc: next_proc,
47
+ creation_proc: creation_proc
48
+ ) if object.nil?
49
+ next_object = next_proc.call(object, key_or_index, original_key)
50
+ creation_proc.call(object, key_or_index, block.call, original_key) if next_object.nil?
51
+ Traverser.new(
52
+ # Refetch it to allow for creation
53
+ next_proc.call(object, key_or_index, original_key),
54
+ key_transformer: key_transformer,
55
+ next_proc: next_proc,
56
+ creation_proc: creation_proc
57
+ )
20
58
  end
59
+
60
+ private
61
+ attr_reader :next_proc, :creation_proc, :key_transformer
21
62
  end
22
63
  end
@@ -1,3 +1,3 @@
1
1
  module Depth
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.0'
3
3
  end
@@ -6,9 +6,13 @@ module Depth
6
6
  let(:actions_class) do
7
7
  Class.new do
8
8
  include Actions
9
- attr_reader :base
10
- def initialize(base)
9
+ attr_reader :base, :next_proc, :creation_proc,
10
+ :key_transformer
11
+ def initialize(base, next_proc:, key_transformer:, creation_proc:)
11
12
  @base = base
13
+ @next_proc = next_proc
14
+ @creation_proc = creation_proc
15
+ @key_transformer = key_transformer
12
16
  end
13
17
  end
14
18
  end
@@ -24,9 +28,71 @@ module Depth
24
28
  ]}
25
29
  end
26
30
 
27
- subject { actions_class.new(hash) }
31
+ let(:next_proc) { proc { |o, k| o[k] } }
32
+ let(:creation_proc) { proc { |o, k, v| o[k] = v } }
33
+ let(:key_transformer) { proc { |_, k| k } }
34
+
35
+ subject do
36
+ actions_class.new(
37
+ hash, next_proc: next_proc,
38
+ creation_proc: creation_proc,
39
+ key_transformer: key_transformer
40
+ )
41
+ end
28
42
 
29
43
  describe '#set' do
44
+ context 'with a key transformer' do
45
+ let(:key_transformer) do
46
+ proc { |_, k|
47
+ next(k) if k.to_s !~ /index_/
48
+ k.gsub(/index_/, '').to_i
49
+ }
50
+ end
51
+
52
+ it 'should still work' do
53
+ route = [['$and', :array], ['index_0', :hash],
54
+ ['#weather', :hash], ['something', :array]]
55
+ expect do
56
+ subject.set(route, :test)
57
+ end.to change { hash['$and'][0]['#weather']['something'] }.to(:test)
58
+ end
59
+ end
60
+
61
+ context 'with a custom creation proc' do
62
+ let(:creation_proc) do
63
+ proc { |o, k, v| o[k] = '2' }
64
+ end
65
+
66
+ it 'should let me change the creation proc' do
67
+ route = [['$and', :array], [0, :hash],
68
+ ['#weather', :hash], ['something', :array]]
69
+ expect do
70
+ subject.set(route, :test)
71
+ end.to change { hash['$and'][0]['#weather']['something'] }.to('2')
72
+
73
+ end
74
+ end
75
+
76
+ context 'with a custom next proc' do
77
+ let(:next_proc) do
78
+ proc { |obj, key|
79
+ if(obj.is_a?(Array))
80
+ obj.at(key)
81
+ else
82
+ obj.fetch(key)
83
+ end
84
+ }
85
+ end
86
+
87
+ it 'should allow me to change how I traverse the route' do
88
+ route = [['$and', :array], [0, :hash],
89
+ ['#weather', :hash], ['something', :array]]
90
+ expect do
91
+ subject.set(route, :test)
92
+ end.to change { hash['$and'][0]['#weather']['something'] }.to(:test)
93
+ end
94
+ end
95
+
30
96
  it 'should let me set an existing value' do
31
97
  route = [['$and', :array], [0, :hash],
32
98
  ['#weather', :hash], ['something', :array]]
@@ -9,9 +9,13 @@ module Depth::Enumeration
9
9
  Class.new do
10
10
  include Depth::Actions
11
11
  include Depth::Enumeration::Enumerable
12
- attr_reader :base
12
+ attr_reader :base, :creation_proc, :next_proc,
13
+ :key_transformer
13
14
  def initialize(base)
14
15
  @base = base
16
+ @creation_proc = proc { |o, k, v| o[k] = v }
17
+ @next_proc = proc { |o, k| o[k] }
18
+ @key_transformer = proc { |_, k| k }
15
19
  end
16
20
  end
17
21
  end
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.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Max
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-01 00:00:00.000000000 Z
11
+ date: 2016-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler