dottie 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,274 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dottie::Freckle do
4
+
5
+ describe 'general' do
6
+
7
+ context 'Hash' do
8
+ let(:freckle) { Dottie::Freckle.new({ 'a' => 'b' }) }
9
+
10
+ it 'makes the original Hash accessible' do
11
+ expect(freckle.hash).to eq({ 'a' => 'b' })
12
+ end
13
+ it 'makes the original Hash accessible' do
14
+ expect(freckle.wrapped_object).to eq({ 'a' => 'b' })
15
+ end
16
+ it 'raises an error if the wrong type is requested' do
17
+ expect{ freckle.array }.to raise_error TypeError
18
+ end
19
+ end
20
+
21
+ context 'Array' do
22
+ let(:freckle) { Dottie::Freckle.new([1, 2]) }
23
+
24
+ it 'makes the original Array accessible' do
25
+ expect(freckle.array).to eq([1, 2])
26
+ end
27
+ it 'makes the original Array accessible' do
28
+ expect(freckle.wrapped_object).to eq([1, 2])
29
+ end
30
+ it 'raises an error if the wrong type is requested' do
31
+ expect{ freckle.hash }.to raise_error TypeError
32
+ end
33
+ end
34
+
35
+ end
36
+
37
+ describe 'reading' do
38
+
39
+ context 'simple' do
40
+ let(:freckle) { Dottie::Freckle.new({ 'a' => 'b', 'c' => { 'd' => 'e' } }) }
41
+
42
+ it 'reads a standard key' do
43
+ expect(freckle['a']).to eq 'b'
44
+ end
45
+ it 'returns nil for a missing standard key' do
46
+ expect(freckle['d']).to be_nil
47
+ end
48
+ it 'reads a dotted key' do
49
+ expect(freckle['c.d']).to eq 'e'
50
+ end
51
+ it 'returns nil for a missing dotted key' do
52
+ expect(freckle['c.e']).to be_nil
53
+ end
54
+ it 'returns nil for a missing nested dotted key' do
55
+ expect(freckle['c.e.g.x.y']).to be_nil
56
+ end
57
+ end
58
+
59
+ context 'ending array indexes' do
60
+ let(:freckle) { Dottie::Freckle.new({ 'a' => 'b', 'c' => %w( d e f ) }) }
61
+
62
+ it 'reads an integer key' do
63
+ expect(freckle['c[0]']).to eq 'd'
64
+ end
65
+ it 'reads a negative integer key' do
66
+ expect(freckle['c[-1]']).to eq 'f'
67
+ end
68
+ it 'reads a named key (first)' do
69
+ expect(freckle['c[first]']).to eq 'd'
70
+ end
71
+ it 'reads a named key (last)' do
72
+ expect(freckle['c[last]']).to eq 'f'
73
+ end
74
+ it 'returns nil for a missing index' do
75
+ expect(freckle['c[4]']).to be_nil
76
+ end
77
+ it 'returns nil for a missing array' do
78
+ expect(freckle['x[4]']).to be_nil
79
+ end
80
+ end
81
+
82
+ context 'middle array indexes' do
83
+ let(:freckle) { Dottie::Freckle.new({ 'a' => 'b', 'c' => [{ 'd' => 'e' }, { 'f' => 'g' }] }) }
84
+
85
+ it 'reads an integer key' do
86
+ expect(freckle['c[0].d']).to eq 'e'
87
+ end
88
+ it 'reads a negative integer key' do
89
+ expect(freckle['c[-1].f']).to eq 'g'
90
+ end
91
+ it 'reads a named key (first)' do
92
+ expect(freckle['c[first].d']).to eq 'e'
93
+ end
94
+ it 'reads a named key (last)' do
95
+ expect(freckle['c[last].f']).to eq 'g'
96
+ end
97
+ it 'returns nil for a missing index' do
98
+ expect(freckle['c[4].r']).to be_nil
99
+ end
100
+ it 'returns nil for a missing array' do
101
+ expect(freckle['x[4].s']).to be_nil
102
+ end
103
+ end
104
+
105
+ context 'consecutive array indexes' do
106
+ let(:freckle) { Dottie::Freckle.new({ 'a' => 'b', 'c' => [ [{}, { 'd' => 'e' }] ] }) }
107
+
108
+ it 'reads an integer key' do
109
+ expect(freckle['c[0][1].d']).to eq 'e'
110
+ end
111
+ it 'reads a negative integer key' do
112
+ expect(freckle['c[-1][1].d']).to eq 'e'
113
+ end
114
+ it 'reads a named key (first)' do
115
+ expect(freckle['c[first][last].d']).to eq 'e'
116
+ end
117
+ it 'reads a named key (last)' do
118
+ expect(freckle['c[last][last].d']).to eq 'e'
119
+ end
120
+ it 'returns nil for a missing index' do
121
+ expect(freckle['c[4][5]']).to be_nil
122
+ end
123
+ it 'returns nil for a missing array' do
124
+ expect(freckle['x[4][5]']).to be_nil
125
+ end
126
+ end
127
+
128
+ end
129
+
130
+ describe 'key existence' do
131
+ let(:freckle) { Dottie::Freckle.new({ 'a' => 'b', 'c' => { 'd' => ['e', 'f', 'g'] } }) }
132
+
133
+ it "finds a standard key" do
134
+ expect(freckle.has_key?('a')).to be_true
135
+ end
136
+ it "does not find a missing standard key" do
137
+ expect(freckle.has_key?('x')).to be_false
138
+ end
139
+ it "finds a Dottie key (Hash value)" do
140
+ expect(freckle.has_key?('c.d')).to be_true
141
+ end
142
+ it "finds a Dottie key (Array element)" do
143
+ expect(freckle.has_key?('c.d[0]')).to be_true
144
+ end
145
+ it "does not find a missing Dottie key (first part is a String)" do
146
+ expect(freckle.has_key?('a.b')).to be_false
147
+ end
148
+ it "does not find a missing Dottie key (first part exists)" do
149
+ expect(freckle.has_key?('c.x')).to be_false
150
+ end
151
+ it "does not find a missing Dottie key (outside Array bounds)" do
152
+ expect(freckle.has_key?('c.d[4]')).to be_false
153
+ end
154
+ it "does not find a missing Dottie key (no part exists)" do
155
+ expect(freckle.has_key?('x.y')).to be_false
156
+ end
157
+ end
158
+
159
+ describe 'fetching' do
160
+ let(:freckle) { Dottie::Freckle.new({ 'a' => 'b', 'c' => { 'd' => ['e', 'f', 'g'] } }) }
161
+
162
+ context 'no default' do
163
+ it 'fetches a standard key' do
164
+ expect(freckle.fetch('a')).to eq 'b'
165
+ end
166
+ it 'fetches a Dottie key (Hash value)' do
167
+ expect(freckle.fetch('c.d')).to eq ['e', 'f', 'g']
168
+ end
169
+ it 'fetches a Dottie key (Array element)' do
170
+ expect(freckle.fetch('c.d[1]')).to eq 'f'
171
+ end
172
+ it 'raises on a missing standard key' do
173
+ expect{ freckle.fetch('x') }.to raise_error KeyError
174
+ end
175
+ it 'raises on a missing Dottie key' do
176
+ expect{ freckle.fetch('x.y') }.to raise_error KeyError
177
+ end
178
+ end
179
+
180
+ context 'with default' do
181
+ it 'fetches a standard key' do
182
+ expect(freckle.fetch('a', 'z')).to eq 'b'
183
+ end
184
+ it 'fetches a Dottie key' do
185
+ expect(freckle.fetch('c.d', 'z')).to eq ['e', 'f', 'g']
186
+ end
187
+ it 'returns a default for a missing standard key' do
188
+ expect(freckle.fetch('x', 'z')).to eq 'z'
189
+ end
190
+ it 'returns a default for a missing Dottie key' do
191
+ expect(freckle.fetch('x', 'z')).to eq 'z'
192
+ end
193
+ end
194
+
195
+ context 'with block' do
196
+ it 'fetches a standard key' do
197
+ expect(freckle.fetch('a'){ |key| key.upcase }).to eq 'b'
198
+ end
199
+ it 'fetches a Dottie key' do
200
+ expect(freckle.fetch('c.d'){ |key| key.upcase }).to eq ['e', 'f', 'g']
201
+ end
202
+ it 'yields to a block for a missing standard key' do
203
+ expect(freckle.fetch('x'){ |key| key.upcase }).to eq 'X'
204
+ end
205
+ it 'yields to a block for a missing Dottie key' do
206
+ expect(freckle.fetch('x.y'){ |key| key.upcase }).to eq 'X.Y'
207
+ end
208
+ end
209
+
210
+ end
211
+
212
+ describe 'writing' do
213
+
214
+ context 'simple' do
215
+ before :each do
216
+ @freckle = Dottie::Freckle.new({ 'a' => 'b', 'c' => { 'd' => 'e' } })
217
+ end
218
+
219
+ it 'overwrites a standard key' do
220
+ @freckle['a'] = 'x'
221
+ expect(@freckle.hash).to eq({ 'a' => 'x', 'c' => { 'd' => 'e' } })
222
+ end
223
+ it 'creates a hash at a non-existent standard key' do
224
+ @freckle['y'] = 'z'
225
+ expect(@freckle.hash).to eq({ 'a' => 'b', 'c' => { 'd' => 'e' }, 'y' => 'z' })
226
+ end
227
+ it 'overwrites a dotted key' do
228
+ @freckle['c.d'] = 'm'
229
+ expect(@freckle.hash).to eq({ 'a' => 'b', 'c' => { 'd' => 'm' } })
230
+ end
231
+ it 'creates a hash at a non-existent dotted key' do
232
+ @freckle['n.o'] = 'p'
233
+ expect(@freckle.hash).to eq({ 'a' => 'b', 'c' => { 'd' => 'e' }, 'n' => { 'o' => 'p' } })
234
+ end
235
+ end
236
+
237
+ context 'array indexes' do
238
+ before :each do
239
+ @freckle = Dottie::Freckle.new({ 'a' => 'b', 'c' => %w( d e f ) })
240
+ end
241
+
242
+ it 'overwrites an array element (positive index)' do
243
+ @freckle['c[0]'] = 'x'
244
+ expect(@freckle.hash).to eq({ 'a' => 'b', 'c' => ['x', 'e', 'f'] })
245
+ end
246
+ it 'overwrites an array element (negative index)' do
247
+ @freckle['c[-2]'] = 'y'
248
+ expect(@freckle.hash).to eq({ 'a' => 'b', 'c' => ['d', 'y', 'f'] })
249
+ end
250
+ it 'overwrites an array element ("first")' do
251
+ @freckle['c[first]'] = 'm'
252
+ expect(@freckle.hash).to eq({ 'a' => 'b', 'c' => ['m', 'e', 'f'] })
253
+ end
254
+ it 'overwrites an array element ("last")' do
255
+ @freckle['c[last]'] = 'n'
256
+ expect(@freckle.hash).to eq({ 'a' => 'b', 'c' => ['d', 'e', 'n'] })
257
+ end
258
+ it 'creates an array at a non-existent key (positive index)' do
259
+ @freckle['r[0]'] = 's'
260
+ expect(@freckle.hash).to eq({ 'a' => 'b', 'c' => ['d', 'e', 'f'], 'r' => ['s'] })
261
+ end
262
+ it 'creates an array at a non-existent key ("first")' do
263
+ @freckle['r[first]'] = 's'
264
+ expect(@freckle.hash).to eq({ 'a' => 'b', 'c' => ['d', 'e', 'f'], 'r' => ['s'] })
265
+ end
266
+ it 'adds an array element' do
267
+ @freckle['c[3]'] = 'g'
268
+ expect(@freckle.hash).to eq({ 'a' => 'b', 'c' => ['d', 'e', 'f', 'g'] })
269
+ end
270
+ end
271
+
272
+ end
273
+
274
+ end
data/spec/hash_spec.rb ADDED
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+ require 'dottie/ext'
3
+
4
+ describe Hash do
5
+
6
+ describe 'Dottie extensions' do
7
+ before :each do
8
+ @hash = { 'a' => 'b', 'c' => { 'd' => 'e' } }
9
+ end
10
+
11
+ context 'untouched' do
12
+ it "should not have Dottie's behavior" do
13
+ expect(@hash['a.b']).to be_nil
14
+ end
15
+ end
16
+
17
+ context 'wrapped' do
18
+ let(:freckle) { @hash.dottie }
19
+
20
+ it 'is no longer a Hash' do
21
+ expect(freckle).to_not be_a Hash
22
+ end
23
+ it 'wraps a Hash in a Dottie::Freckle' do
24
+ expect(freckle).to be_a Dottie::Freckle
25
+ end
26
+ it 'acts like a regular Hash for standard keys' do
27
+ expect(freckle['a']).to eq 'b'
28
+ end
29
+ it "has Dottie's behavior" do
30
+ expect(freckle['c.d']).to eq 'e'
31
+ end
32
+ it "does not add Dottie's behavior to the original Hash" do
33
+ expect(@hash['a.b']).to be_nil
34
+ end
35
+ end
36
+
37
+ context 'mixed in' do
38
+ before :each do
39
+ @hash.dottie!
40
+ end
41
+
42
+ it 'is still a Hash' do
43
+ expect(@hash).to be_a Hash
44
+ end
45
+ it 'acts like a regular Hash for standard keys' do
46
+ expect(@hash['a']).to eq 'b'
47
+ end
48
+ it "adds Dottie's behavior to a Hash" do
49
+ expect(@hash['c.d']).to eq 'e'
50
+ end
51
+ end
52
+
53
+ end
54
+
55
+ end
@@ -0,0 +1 @@
1
+ require 'dottie'
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dottie
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Nick Pearson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-05-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: |-
56
+ Deeply access nested Hash/Array data structures
57
+ without checking for the existence of every node
58
+ along the way.
59
+ email:
60
+ - nick@banyantheory.com
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - ".gitignore"
66
+ - Gemfile
67
+ - LICENSE.txt
68
+ - README.md
69
+ - Rakefile
70
+ - dottie.gemspec
71
+ - lib/dottie.rb
72
+ - lib/dottie/ext.rb
73
+ - lib/dottie/ext/array.rb
74
+ - lib/dottie/ext/hash.rb
75
+ - lib/dottie/freckle.rb
76
+ - lib/dottie/helper.rb
77
+ - lib/dottie/methods.rb
78
+ - lib/dottie/version.rb
79
+ - spec/array_spec.rb
80
+ - spec/dottie_spec.rb
81
+ - spec/freckle_spec.rb
82
+ - spec/hash_spec.rb
83
+ - spec/spec_helper.rb
84
+ homepage: https://github.com/nickpearson/dottie
85
+ licenses:
86
+ - MIT
87
+ metadata: {}
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 2.2.2
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: Deep Hash and Array access with dotted keys
108
+ test_files:
109
+ - spec/array_spec.rb
110
+ - spec/dottie_spec.rb
111
+ - spec/freckle_spec.rb
112
+ - spec/hash_spec.rb
113
+ - spec/spec_helper.rb
114
+ has_rdoc: