lab42_nhash 0.1.1 → 0.1.2

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: dfa964b499cd8f9c9fb458f0082eacf0f990cfac
4
- data.tar.gz: f5c06457ecdd6652fd05a33e768791192993a37d
3
+ metadata.gz: 61f49c29e0db80ae41ba77a021fa52ddff6c8358
4
+ data.tar.gz: d82b50f5129c0dc580647654593f64179a0a95fb
5
5
  SHA512:
6
- metadata.gz: aacab0eb78da5bbeb5b945624e0c2fa058634ba87731dee6803cae4caf27c9e9d21f8910b18a75579528a167d556417b1caeb25bdcea512ca31fd3e614d3f779
7
- data.tar.gz: 7aa8904790917d875576b024692427ea49fe3b252096aca527b3c25f101d8afb7a035822262f9a41533cc6d4c402ef68eeefa9afecd893d92f3a86f8c9e8d52d
6
+ metadata.gz: 7d2f0c0e1426d9034430be22df2f220463413b75d13069e40533aa8e31226493b1ae5fce8a887a51f1ab6ce0b40fe0964f03ede6275f7ee04635106b07c1775b
7
+ data.tar.gz: 12bab1e9b0f31058465e54b72fb12cce5641148c29ae864eeac1e5636b2c5afb15e4b10c6a6555a95fb55640391e9a200c47474220bfb2398a0cb5d373b48bd9
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- lab42_nhash (0.1.1)
4
+ lab42_nhash (0.1.2)
5
5
  forwarder2 (~> 0.2)
6
6
  ruby_parser (~> 3.6)
7
7
 
@@ -45,6 +45,59 @@ And that we can also use interpolation:
45
45
  # entries[0].get!(:value).assert == '42'
46
46
  ```
47
47
 
48
+ ### Enhanced Search
49
+
50
+ `NHash::Enum` of course implements `Enumerable`. However, when looking for keys we need to rescue from `KeyError` very frequently.
51
+
52
+ Here is a demonstration of that.
53
+
54
+ ```ruby
55
+ nh = NHash.new(
56
+ entries: [
57
+ {a: 1},
58
+ {b: 2}
59
+ ])
60
+ .with_indifferent_access
61
+ entries = nh.get :entries
62
+ ```
63
+
64
+ In order to find `b` the quite obvious code is
65
+
66
+ ```ruby
67
+ entries.find{ |entry|
68
+ begin
69
+ entry.get(:b)
70
+ rescue KeyError
71
+ end
72
+ }.get(:b).assert == 2
73
+ ```
74
+
75
+ Now that code is not very readable, is it? Being cluttered by the rescue block and needing to invoke the get again?
76
+
77
+ Here is how we would like to write (and read) that kind of code:
78
+
79
+ ```ruby
80
+ entries.get{ |entry|
81
+ entry.get :b
82
+ }.assert == 2
83
+ ```
84
+
85
+ This can even be shortened to
86
+
87
+ ```ruby
88
+ entries.get{ 2 * get(:b) }
89
+ .assert == 4
90
+ ```
91
+
92
+ or
93
+
94
+ ```ruby
95
+ entries.get(:b).assert == 2
96
+ ```
97
+
98
+
99
+
100
+
48
101
 
49
102
 
50
103
 
@@ -1,5 +1,7 @@
1
1
  require 'forwarder'
2
2
 
3
+ require_relative 'invocation'
4
+
3
5
  module Lab42
4
6
  class NHash
5
7
  class Enum
@@ -11,12 +13,20 @@ module Lab42
11
13
  forward :last!, to_object: :self, as: :fetch!, with: -1
12
14
 
13
15
  include Enumerable
16
+ include Invocation
14
17
 
15
18
  attr_reader :parent
16
19
 
17
20
  def [] idx
18
21
  Lab42::NHash.from_value @enum[idx], @options
19
22
  end
23
+
24
+ def each blk=nil, &block
25
+ behavior = blk || block
26
+ @enum.each do | ele |
27
+ behavior.( Lab42::NHash.from_value ele, @options )
28
+ end
29
+ end
20
30
 
21
31
  def fetch! idx
22
32
  result = self[ idx ]
@@ -24,6 +34,12 @@ module Lab42
24
34
 
25
35
  ERB.new( result ).result @parent.current_binding
26
36
  end
37
+
38
+ def get keyexp=nil, &block
39
+ behavior = block || keyexp
40
+ raise ArgumentError, 'need key or behavior' unless behavior
41
+ Proc === behavior ? _get_with_behavior( behavior ) : _get_with_key( keyexp )
42
+ end
27
43
 
28
44
  private
29
45
  def initialize enum, options
@@ -32,6 +48,26 @@ module Lab42
32
48
  @options = options
33
49
  end
34
50
 
51
+ def _get_with_key keyexp
52
+ each do |ele, sentinel|
53
+ begin
54
+ return ele.get keyexp
55
+ rescue KeyError
56
+ end
57
+ end
58
+ raise KeyError, "key not found: #{keyexp.inspect}"
59
+ end
60
+
61
+ def _get_with_behavior behavior
62
+ each do |ele, sentinel|
63
+ begin
64
+ return _invoke behavior, ele
65
+ rescue KeyError
66
+ end
67
+ end
68
+ raise KeyError, "key not found: #{keyexp.inspect}"
69
+
70
+ end
35
71
  end # class Enum
36
72
  end # class NHash
37
73
  end # module Lab42
@@ -1,5 +1,5 @@
1
1
  module Lab42
2
2
  class NHash
3
- VERSION = '0.1.1'
3
+ VERSION = '0.1.2'
4
4
  end # class NHash
5
5
  end # module Lab42
@@ -1,41 +1,33 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe NHash::Enum do
4
- subject do
5
- nh = NHash.new(
6
- a: 42,
7
- entries: [
8
- { val: '<%= get :a %>' },
9
- '<%= get(:a) * 2 %>',
10
- 21
11
- ] )
12
- .with_indifferent_access
13
- end
14
- let(:enum){ subject.get :entries }
15
4
 
16
- it 'is returned for arrays' do
17
- expect( subject.get :entries ).to be_instance_of described_class
18
- end
5
+ context 'Enumerable behavior' do
6
+ context 'Hashes' do
7
+ subject do
8
+ NHash.new( entries: [{a: 1}] ).with_indifferent_access
9
+ end
10
+ let(:entries){ subject.get :entries }
19
11
 
20
- context 'behaves like an array' do
21
- it 'for #[]' do
22
- expect( enum[2] ).to eq 21
23
- end
24
- it 'for #first' do
25
- expect( enum.first.get :val ).to eq '<%= get :a %>'
26
- end
27
- it 'for #last' do
28
- expect( enum.last ).to eq 21
29
- end
30
- end # context :behaves
12
+ it 'are yielded as NHash instances' do
13
+ entries.each do | entry |
14
+ expect( entry ).to be_kind_of NHash
15
+ end
16
+ end
17
+ end # context 'yields NHashes'
31
18
 
32
- context 'preservers the context' do
33
- it 'evaluates with indifferent access' do
34
- expect( enum.first.get('val') ).to eq '<%= get :a %>'
35
- end
19
+ context 'Arrays' do
20
+ subject do
21
+ NHash.new( entries: [[{a:1}]] ).with_indifferent_access
22
+ end
23
+ let(:entries){ subject.get :entries }
24
+ it 'are yielded as NHash::Enum instances' do
25
+ entries.each do | entry |
26
+ expect( entry ).to be_kind_of described_class
27
+ end
28
+ end
29
+
30
+ end # context 'yields NHash::Enum instances'
31
+ end # context 'Enumerable behavior'
36
32
 
37
- it 'interpolates in the context of the original object' do
38
- expect( enum.first.get!('val') ).to eq '42'
39
- end
40
- end # context 'preservers the context'
41
33
  end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe NHash::Enum do
4
+
5
+ subject do
6
+ NHash.new(
7
+ entries: [
8
+ {a: 1},
9
+ {b: 2}
10
+ ]
11
+ ).with_indifferent_access
12
+ end
13
+ let(:entries){ subject.get :entries }
14
+
15
+
16
+ context 'get with keys' do
17
+ it 'finds a key' do
18
+ expect( entries.get :a ).to eq 1
19
+ expect( entries.get :b ).to eq 2
20
+ end
21
+
22
+ it '... or not' do
23
+ expect( ->{ entries.get :c } ).to raise_error KeyError
24
+ end
25
+ end # context 'get with keys'
26
+
27
+ context 'get with blox' do
28
+ it 'finds a key and returns the bloxs return value' do
29
+ expect( entries.get{ |e| e.get(:b) * 2 } ).to eq 4
30
+ expect( entries.get(->(e){ e.get(:b) * 2 }) ).to eq 4
31
+ end
32
+ it 'can instance exec the behavior' do
33
+ expect( entries.get{ get(:b) + 1 } ).to eq 3
34
+ expect( entries.get(->{ get(:b) + 1 }) ).to eq 3
35
+ end
36
+ end # context 'get with blox'
37
+
38
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe NHash::Enum do
4
+ subject do
5
+ nh = NHash.new(
6
+ a: 42,
7
+ entries: [
8
+ { val: '<%= get :a %>' },
9
+ '<%= get(:a) * 2 %>',
10
+ 21
11
+ ] )
12
+ .with_indifferent_access
13
+ end
14
+ let(:enum){ subject.get :entries }
15
+
16
+ it 'is returned for arrays' do
17
+ expect( subject.get :entries ).to be_instance_of described_class
18
+ end
19
+
20
+ context 'behaves like an array' do
21
+ it 'for #[]' do
22
+ expect( enum[2] ).to eq 21
23
+ end
24
+ it 'for #first' do
25
+ expect( enum.first.get :val ).to eq '<%= get :a %>'
26
+ end
27
+ it 'for #last' do
28
+ expect( enum.last ).to eq 21
29
+ end
30
+ end # context :behaves
31
+
32
+ context 'behaves like an Enumerable' do
33
+ it 'via Lab42::NHash::Enum' do
34
+ expect( enum ).to be_kind_of described_class
35
+ expect( described_class ).to be < Enumerable
36
+ end
37
+
38
+ end # context 'behaves like an Enumerable'
39
+
40
+ context 'preservers the context' do
41
+ it 'evaluates with indifferent access' do
42
+ expect( enum.first.get('val') ).to eq '<%= get :a %>'
43
+ end
44
+
45
+ it 'interpolates in the context of the original object' do
46
+ expect( enum.first.get!('val') ).to eq '42'
47
+ end
48
+ end # context 'preservers the context'
49
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lab42_nhash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Dober
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-27 00:00:00.000000000 Z
11
+ date: 2014-05-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: forwarder2
@@ -168,6 +168,8 @@ files:
168
168
  - spec/unit/afixes/prefix_spec.rb
169
169
  - spec/unit/afixes/suffix_spec.rb
170
170
  - spec/unit/compound/enum_spec.rb
171
+ - spec/unit/compound/get_spec.rb
172
+ - spec/unit/compound/hash_enum_spec.rb
171
173
  - spec/unit/compound/nhash_spec.rb
172
174
  - spec/unit/factories/from_sources_using_hashes_spec.rb
173
175
  - spec/unit/factories/from_sources_using_yaml_files_spec.rb
@@ -224,6 +226,8 @@ test_files:
224
226
  - spec/unit/afixes/prefix_spec.rb
225
227
  - spec/unit/afixes/suffix_spec.rb
226
228
  - spec/unit/compound/enum_spec.rb
229
+ - spec/unit/compound/get_spec.rb
230
+ - spec/unit/compound/hash_enum_spec.rb
227
231
  - spec/unit/compound/nhash_spec.rb
228
232
  - spec/unit/factories/from_sources_using_hashes_spec.rb
229
233
  - spec/unit/factories/from_sources_using_yaml_files_spec.rb