hashr 2.0.0.rc1 → 2.0.0.rc2

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: 865d5c744eb989eb6faa51b252a52b83ac31fd49
4
- data.tar.gz: a69e87efba10818c1af7036e02d75327210dbc3b
3
+ metadata.gz: 71976fe0fa3a09290f4f79dae7e349480579ad9d
4
+ data.tar.gz: 55dd79646eaf06b86937ced119b3d4b488780de4
5
5
  SHA512:
6
- metadata.gz: 1e2285af349146a905c6bcc53f5bdacc9d644f2ca48e05e69d700e18082d2285dd1b49e16670808a470e72e6ced4795ceb614d6d4eeded4310e61c9f1ffb559e
7
- data.tar.gz: 993a3e986b50d2c9c34bd2ce153f2a25c10d0530962cca561880361f9080d83cdbb87f83de34b3dc11029ed88a5cf479d9de259396dc7d09b089f00d9820a336
6
+ metadata.gz: 3b9fe63ebf17bf22d5253887afbf67e8b090462df7b64291a89b425b1e32665b405905d1984371e13752a0d18e54f53ee700f0997b571f80291db58bd61dbfee
7
+ data.tar.gz: a46cc5aad1af026c325080a73a01045ef4878f66c2072da21f0265024d9a63c6e5567a53bbfacf36d926b706821639964e60d300960711cd69dae781e67f72cb
@@ -76,7 +76,7 @@ class Hashr < BasicObject
76
76
 
77
77
  def to_h
78
78
  @data.inject({}) do |hash, (key, value)|
79
- hash.merge(key => value.respond_to?(:to_h) ? value.to_h : value)
79
+ hash.merge(key => value.is_a?(Hashr) || value.is_a?(Hash) ? value.to_h : value)
80
80
  end
81
81
  end
82
82
  alias to_hash to_h
@@ -1,3 +1,3 @@
1
1
  class Hashr < BasicObject
2
- VERSION = '2.0.0.rc1'
2
+ VERSION = '2.0.0.rc2'
3
3
  end
@@ -0,0 +1,15 @@
1
+ describe Hash do
2
+ describe 'deep_symbolize_keys' do
3
+ it 'symbolizes keys on nested hashes' do
4
+ hash = { 'foo' => { 'bar' => 'bar' } }
5
+ expected = { :foo => { :bar => 'bar' } }
6
+ expect(hash.deep_symbolize_keys).to eq(expected)
7
+ end
8
+
9
+ it 'walks arrays' do
10
+ hash = { 'foo' => [{ 'bar' => 'bar', 'baz' => { 'buz' => 'buz' } }] }
11
+ expected = { :foo => [{ :bar => 'bar', :baz => { :buz => 'buz' } }] }
12
+ expect(hash.deep_symbolize_keys).to eq(expected)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ describe Hashr::Delegate::Conditional do
2
+ let(:klass) { Class.new(Hashr) { include Hashr::Delegate::Conditional } }
3
+
4
+ it 'delegates key?' do
5
+ hashr = klass.new(foo: 'foo')
6
+ expect(hashr.key?(:foo)).to eq(true)
7
+ end
8
+
9
+ it 'delegates select' do
10
+ hashr = klass.new(foo: 'foo', bar: 'bar')
11
+ expect(hashr.select { |key, value| key == :bar }.to_h).to eq(bar: 'bar')
12
+ end
13
+
14
+ it 'delegates delete' do
15
+ hashr = klass.new(foo: 'foo', bar: 'bar')
16
+ hashr.delete(:foo)
17
+ expect(hashr.to_h).to eq(bar: 'bar')
18
+ end
19
+ end
@@ -0,0 +1,64 @@
1
+ describe Hashr::Env do
2
+ let(:klass) do
3
+ Class.new(Hashr) do
4
+ extend Hashr::Env
5
+
6
+ self.env_namespace = 'hashr'
7
+
8
+ define string: 'string',
9
+ hash: { key: 'value' },
10
+ array: ['foo', 'bar'],
11
+ bool: false
12
+ end
13
+ end
14
+
15
+ after do
16
+ ENV.keys.each { |key| ENV.delete(key) if key.start_with?('HASHR_') }
17
+ end
18
+
19
+ it 'defaults to an env var' do
20
+ ENV['HASHR_STRING'] = 'env string'
21
+ expect(klass.new.string).to eq('env string')
22
+ end
23
+
24
+ it 'defaults to a nested env var' do
25
+ ENV['HASHR_HASH_KEY'] = 'env value'
26
+ expect(klass.new.hash.key).to eq('env value')
27
+ end
28
+
29
+ describe 'type casts based on the default' do
30
+ describe 'to boolean' do
31
+ it 'true given' do
32
+ ENV['HASHR_BOOL'] = 'true'
33
+ expect(klass.new.bool).to eq(true)
34
+ end
35
+
36
+ it 'false given' do
37
+ ENV['HASHR_BOOL'] = 'false'
38
+ expect(klass.new.bool).to eq(false)
39
+ end
40
+
41
+ it 'empty string given' do
42
+ ENV['HASHR_BOOL'] = ''
43
+ expect(klass.new.bool).to eq(false)
44
+ end
45
+ end
46
+
47
+ describe 'to an array' do
48
+ it 'splits a comma-separated string' do
49
+ ENV['HASHR_ARRAY'] = 'env foo,env bar'
50
+ expect(klass.new.array).to eq(['env foo', 'env bar'])
51
+ end
52
+
53
+ it 'returns an empty array for an empty string' do
54
+ ENV['HASHR_ARRAY'] = ''
55
+ expect(klass.new.array).to eq([])
56
+ end
57
+ end
58
+ end
59
+
60
+ it 'data takes precedence over an env var' do
61
+ ENV['HASHR_STRING'] = 'env string'
62
+ expect(klass.new(string: 'data string').string).to eq('data string')
63
+ end
64
+ end
@@ -0,0 +1,266 @@
1
+ describe Hashr do
2
+ describe 'initialization' do
3
+ it 'takes nil' do
4
+ expect { Hashr.new(nil) }.to_not raise_error
5
+ end
6
+
7
+ it 'does not explode on a numerical key' do
8
+ expect { Hashr.new(1 => 2) }.to_not raise_error
9
+ end
10
+
11
+ it 'does not explode on a true key' do
12
+ expect { Hashr.new(true => 'on') }.to_not raise_error
13
+ end
14
+
15
+ it 'raises an ArgumentError when given a string' do
16
+ expect { Hashr.new('foo') }.to raise_error(ArgumentError)
17
+ end
18
+
19
+ it 'passing a block allows to define methods on the singleton class' do
20
+ hashr = Hashr.new(count: 5) do
21
+ def count
22
+ @data.count
23
+ end
24
+ end
25
+ expect(hashr.count).to eq(5)
26
+ end
27
+ end
28
+
29
+ describe 'defined?' do
30
+ it 'returns true when a key is defined' do
31
+ hashr = Hashr.new(foo: 'foo')
32
+ expect(hashr.defined?(:foo)).to eq(true)
33
+ end
34
+
35
+ it 'returns false when a key is not defined' do
36
+ hashr = Hashr.new(foo: 'foo')
37
+ expect(hashr.defined?(:bar)).to eq(false)
38
+ end
39
+
40
+ it 'works with a numerical key' do
41
+ hashr = Hashr.new(1 => 'foo')
42
+ expect(hashr.defined?(1)).to eq(true)
43
+ end
44
+
45
+ it 'works with a true key' do
46
+ hashr = Hashr.new(true => 'foo')
47
+ expect(hashr.defined?(true)).to eq(true)
48
+ end
49
+
50
+ it 'is indifferent about symbols/strings (string given, symbol used)' do
51
+ hashr = Hashr.new('foo' => 'bar')
52
+ expect(hashr.defined?(:foo)).to eq(true)
53
+ end
54
+
55
+ it 'is indifferent about symbols/strings (symbol given, string used)' do
56
+ hashr = Hashr.new(foo: :bar)
57
+ expect(hashr.defined?('foo')).to eq(true)
58
+ end
59
+ end
60
+
61
+ describe 'hash access' do
62
+ it 'is indifferent about symbols/strings (string given, symbol used)' do
63
+ hashr = Hashr.new('foo' => { 'bar' => 'baz' })
64
+ expect(hashr[:foo][:bar]).to eq('baz')
65
+ end
66
+
67
+ it 'is indifferent about symbols/strings (symbol given, string used)' do
68
+ hashr = Hashr.new(foo: { bar: 'baz' })
69
+ expect(hashr['foo']['bar']).to eq('baz')
70
+ end
71
+
72
+ it 'allows accessing keys with Hash core method names (count)' do
73
+ expect(Hashr.new(count: 2).count).to eq(2)
74
+ end
75
+
76
+ it 'allows accessing keys with Hash core method names (key)' do
77
+ expect(Hashr.new(key: 'key').key).to eq('key')
78
+ end
79
+ end
80
+
81
+ describe 'hash assignment' do
82
+ let(:hashr) { Hashr.new }
83
+
84
+ it 'works with a string key' do
85
+ hashr['foo'] = 'foo'
86
+ expect(hashr.foo).to eq('foo')
87
+ end
88
+
89
+ it 'works with a symbol key' do
90
+ hashr[:foo] = 'foo'
91
+ expect(hashr.foo).to eq('foo')
92
+ end
93
+ end
94
+
95
+ describe 'method access' do
96
+ describe 'on an existing key' do
97
+ it 'returns the value' do
98
+ expect(Hashr.new(foo: 'foo').foo).to eq('foo')
99
+ end
100
+
101
+ it 'returns a nested hash' do
102
+ expect(Hashr.new(foo: { bar: 'bar' }).foo).to eq(bar: 'bar')
103
+ end
104
+
105
+ it 'returns a nested array' do
106
+ expect(Hashr.new(foo: ['bar', 'buz']).foo).to eq(['bar', 'buz'])
107
+ end
108
+ end
109
+
110
+ describe 'on an existing nested key' do
111
+ it 'returns the value' do
112
+ expect(Hashr.new(foo: { bar: 'bar' }).foo.bar).to eq('bar')
113
+ end
114
+
115
+ it 'returns a nested array' do
116
+ expect(Hashr.new(foo: { bar: ['bar', 'buz'] }).foo.bar).to eq(['bar', 'buz'])
117
+ end
118
+ end
119
+
120
+ describe 'on an non-existing key' do
121
+ it 'it returns nil' do
122
+ expect(Hashr.new(foo: 'foo').bar).to eq(nil)
123
+ end
124
+
125
+ it 'it returns nil (nested key)' do
126
+ expect(Hashr.new(foo: { bar: 'bar' }).foo.baz).to eq(nil)
127
+ end
128
+ end
129
+
130
+ describe 'predicate methods' do
131
+ it 'returns true if the key has a value' do
132
+ expect(Hashr.new(foo: { bar: 'bar' }).foo.bar?).to eq(true)
133
+ end
134
+
135
+ it 'returns false if the key does not have a value' do
136
+ expect(Hashr.new(foo: { bar: 'bar' }).foo.baz?).to eq(false)
137
+ end
138
+ end
139
+
140
+ describe 'respond_to?' do
141
+ it 'returns true for existing keys' do
142
+ expect(Hashr.new(foo: 'bar').respond_to?(:foo)).to eq(true)
143
+ end
144
+
145
+ it 'returns false for missing keys' do
146
+ expect(Hashr.new.respond_to?(:foo)).to eq(true)
147
+ end
148
+ end
149
+ end
150
+
151
+ describe 'method assignment' do
152
+ let(:hashr) { Hashr.new }
153
+
154
+ it 'assigns a string' do
155
+ hashr.foo = 'foo'
156
+ expect(hashr.foo).to eq('foo')
157
+ end
158
+
159
+ it 'converts a hash into a Hashr instance' do
160
+ hashr.foo = { bar: { baz: 'baz' } }
161
+ expect(hashr.foo.bar.baz).to eq('baz')
162
+ end
163
+ end
164
+
165
+ describe 'values_at' do
166
+ let(:hashr) { Hashr.new(foo: 'foo', bar: 'bar') }
167
+
168
+ it 'returns values for the given keys' do
169
+ expect(hashr.values_at(:foo, :bar)).to eq(['foo', 'bar'])
170
+ end
171
+ end
172
+
173
+ describe 'is_a?' do
174
+ let(:klass) { Class.new(Class.new(Hashr)) { default foo: 'foo' } }
175
+
176
+ it 'returns true if the object has the given superclass' do
177
+ expect(klass.new.is_a?(Hashr)).to eq(true)
178
+ end
179
+
180
+ it 'returns false if the object does not have the given superclass' do
181
+ expect(klass.new.is_a?(Hash)).to eq(false)
182
+ end
183
+ end
184
+
185
+ describe 'conversion' do
186
+ let(:hash) { Hashr.new(foo: { 'bar' => 'baz' }).to_h }
187
+
188
+ it 'converts the Hashr instance to a hash' do
189
+ expect(hash.class).to eq(Hash)
190
+ end
191
+
192
+ it 'converts nested instances to hashes' do
193
+ expect(hash[:foo].class).to eq(Hash)
194
+ end
195
+
196
+ it 'populates the hash with the symbolized keys' do
197
+ expect(hash[:foo][:bar]).to eq('baz')
198
+ end
199
+ end
200
+
201
+ describe 'defaults' do
202
+ describe 'using a symbolized hash' do
203
+ let(:klass) { Class.new(Hashr) { default foo: 'foo' } }
204
+
205
+ it 'defines the default' do
206
+ expect(klass.new['foo']).to eq('foo')
207
+ end
208
+ end
209
+
210
+ describe 'using a stringified hash' do
211
+ let(:klass) { Class.new(Hashr) { default 'foo' => 'foo' } }
212
+
213
+ it 'defines the default' do
214
+ expect(klass.new[:foo]).to eq('foo')
215
+ end
216
+ end
217
+
218
+ describe 'with a nested hash' do
219
+ let(:klass) { Class.new(Hashr) { default foo: { bar: { baz: 'baz' } } } }
220
+
221
+ it 'defines the default' do
222
+ expect(klass.new['foo'][:bar]['baz']).to eq('baz')
223
+ end
224
+ end
225
+
226
+ describe 'with a nested array' do
227
+ let(:klass) { Class.new(Hashr) { default foo: ['bar'] } }
228
+
229
+ it 'defines the default' do
230
+ expect(klass.new.foo.first).to eq('bar')
231
+ end
232
+ end
233
+
234
+ describe 'keeps existing defaults' do
235
+ let(:klass) { Class.new(Hashr) { default foo: 'foo'; default bar: 'bar' } }
236
+
237
+ it 'defines the existing default' do
238
+ expect(klass.new.foo).to eq('foo')
239
+ end
240
+
241
+ it 'defines the new default' do
242
+ expect(klass.new.bar).to eq('bar')
243
+ end
244
+ end
245
+
246
+ describe 'deep_merges inherited defaults' do
247
+ let(:klass) { Class.new(Class.new(Hashr) { default foo: 'foo' }) { default bar: 'bar' } }
248
+
249
+ it 'defines the inherited default' do
250
+ expect(klass.new.foo).to eq('foo')
251
+ end
252
+
253
+ it 'defines the default' do
254
+ expect(klass.new.bar).to eq('bar')
255
+ end
256
+ end
257
+ end
258
+
259
+ describe 'constant lookup' do
260
+ let(:klass) { Class.new(Hashr) { def env; ENV; end } }
261
+
262
+ it 'finds global consts' do
263
+ expect(klass.new.env).to eq(ENV)
264
+ end
265
+ end
266
+ end
@@ -0,0 +1 @@
1
+ require 'hashr'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hashr
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.rc1
4
+ version: 2.0.0.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sven Fuchs
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-07 00:00:00.000000000 Z
11
+ date: 2015-10-15 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Simple Hash extension to make working with nested hashes (e.g. for configuration)
14
14
  easier and less error-prone.
@@ -26,6 +26,11 @@ files:
26
26
  - lib/hashr/delegate/hash.rb
27
27
  - lib/hashr/env.rb
28
28
  - lib/hashr/version.rb
29
+ - spec/core_ext_spec.rb
30
+ - spec/hashr/delegate/conditional_spec.rb
31
+ - spec/hashr/env_spec.rb
32
+ - spec/hashr_spec.rb
33
+ - spec/spec_helper.rb
29
34
  homepage: http://github.com/svenfuchs/hashr
30
35
  licenses: []
31
36
  metadata: {}