depth 0.3.0 → 0.4.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 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