hashr 2.0.0.rc1 → 2.0.0.rc2
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 +4 -4
- data/lib/hashr.rb +1 -1
- data/lib/hashr/version.rb +1 -1
- data/spec/core_ext_spec.rb +15 -0
- data/spec/hashr/delegate/conditional_spec.rb +19 -0
- data/spec/hashr/env_spec.rb +64 -0
- data/spec/hashr_spec.rb +266 -0
- data/spec/spec_helper.rb +1 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71976fe0fa3a09290f4f79dae7e349480579ad9d
|
4
|
+
data.tar.gz: 55dd79646eaf06b86937ced119b3d4b488780de4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b9fe63ebf17bf22d5253887afbf67e8b090462df7b64291a89b425b1e32665b405905d1984371e13752a0d18e54f53ee700f0997b571f80291db58bd61dbfee
|
7
|
+
data.tar.gz: a46cc5aad1af026c325080a73a01045ef4878f66c2072da21f0265024d9a63c6e5567a53bbfacf36d926b706821639964e60d300960711cd69dae781e67f72cb
|
data/lib/hashr.rb
CHANGED
@@ -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.
|
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
|
data/lib/hashr/version.rb
CHANGED
@@ -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
|
data/spec/hashr_spec.rb
ADDED
@@ -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
|
data/spec/spec_helper.rb
ADDED
@@ -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.
|
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-
|
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: {}
|