insensitive_hash 0.2.2 → 0.2.3
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.
- data/CHANGELOG.markdown +4 -0
- data/lib/insensitive_hash/insensitive_hash.rb +23 -10
- data/lib/insensitive_hash/version.rb +1 -1
- data/test/test_insensitive_hash.rb +85 -32
- metadata +4 -4
data/CHANGELOG.markdown
CHANGED
@@ -11,6 +11,7 @@ class InsensitiveHash < Hash
|
|
11
11
|
|
12
12
|
@key_map = {}
|
13
13
|
@underscore = false
|
14
|
+
@safe = false
|
14
15
|
end
|
15
16
|
|
16
17
|
# Sets whether to replace spaces in String keys to underscores
|
@@ -35,6 +36,19 @@ class InsensitiveHash < Hash
|
|
35
36
|
def underscore?
|
36
37
|
@underscore
|
37
38
|
end
|
39
|
+
|
40
|
+
# Sets whether to detect key clashes
|
41
|
+
# @param [Boolean]
|
42
|
+
# @return [Boolean]
|
43
|
+
def safe= s
|
44
|
+
raise ArgumentError.new("Not true or false") unless [true, false].include?(s)
|
45
|
+
@safe = s
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [Boolean] Key-clash detection enabled?
|
49
|
+
def safe?
|
50
|
+
@safe
|
51
|
+
end
|
38
52
|
|
39
53
|
# Returns a normal, sensitive Hash
|
40
54
|
# @return [Hash]
|
@@ -95,19 +109,18 @@ class InsensitiveHash < Hash
|
|
95
109
|
end
|
96
110
|
|
97
111
|
def replace other
|
112
|
+
super other
|
113
|
+
|
98
114
|
# TODO
|
99
115
|
# What is the correct behavior of replace when the other hash is not an InsensitiveHash?
|
100
116
|
# underscore property precedence: other => self (FIXME)
|
101
|
-
|
102
|
-
|
117
|
+
self.underscore = other.respond_to?(:underscore?) ? other.underscore? : self.underscore?
|
118
|
+
self.safe = other.safe? if other.respond_to?(:safe?)
|
103
119
|
|
104
|
-
|
105
|
-
self.
|
106
|
-
|
107
|
-
|
108
|
-
clear
|
109
|
-
other.each do |k, v|
|
110
|
-
self[k] = v
|
120
|
+
@key_map.clear
|
121
|
+
self.each do |k, v|
|
122
|
+
ekey = encode k, @underscore
|
123
|
+
@key_map[ekey] = k
|
111
124
|
end
|
112
125
|
end
|
113
126
|
|
@@ -166,7 +179,7 @@ private
|
|
166
179
|
def detect_clash hash, us
|
167
180
|
hash.keys.map { |k| encode k, us }.tap { |ekeys|
|
168
181
|
raise KeyClashError.new("Key clash detected") if ekeys != ekeys.uniq
|
169
|
-
}
|
182
|
+
} if @safe
|
170
183
|
end
|
171
184
|
end
|
172
185
|
|
@@ -6,6 +6,20 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
6
6
|
require 'insensitive_hash/minimal'
|
7
7
|
|
8
8
|
class TestInsensitiveHash < Test::Unit::TestCase
|
9
|
+
def eight?
|
10
|
+
RUBY_VERSION =~ /^1\.8\./
|
11
|
+
end
|
12
|
+
|
13
|
+
def assert_keys set1, set2
|
14
|
+
if eight?
|
15
|
+
assert_equal set1.sort { |a, b| a.to_s <=> b.to_s },
|
16
|
+
set2.sort { |a, b| a.to_s <=> b.to_s }
|
17
|
+
else
|
18
|
+
assert_equal set1, set2
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
9
23
|
def test_has_key_set
|
10
24
|
ih = InsensitiveHash.new
|
11
25
|
ih['a'] = 1
|
@@ -19,12 +33,11 @@ class TestInsensitiveHash < Test::Unit::TestCase
|
|
19
33
|
assert_equal 2, ih[a]
|
20
34
|
end
|
21
35
|
|
22
|
-
|
36
|
+
assert_keys ['A'], ih.keys
|
23
37
|
assert_equal [2], ih.values
|
24
38
|
|
25
39
|
ih[:A] = 4
|
26
|
-
|
27
|
-
assert_equal [:A], ih.keys
|
40
|
+
assert_keys [:A], ih.keys
|
28
41
|
assert_equal [4], ih.values
|
29
42
|
|
30
43
|
ih[:b] = { :c => 5 }
|
@@ -91,14 +104,16 @@ class TestInsensitiveHash < Test::Unit::TestCase
|
|
91
104
|
end
|
92
105
|
|
93
106
|
# Preserving default_proc
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
107
|
+
unless eight?
|
108
|
+
hash2 = {}
|
109
|
+
hash2.replace hash
|
110
|
+
hash2.default_proc = proc { |h, k| h[k] = :default }
|
111
|
+
|
112
|
+
ihash2 = hash2.insensitive.insensitive.insensitive
|
113
|
+
assert !ihash2.has_key?(:anything)
|
114
|
+
assert_equal :default, ihash2[:anything]
|
115
|
+
assert ihash2.has_key?(:anything)
|
116
|
+
end
|
102
117
|
|
103
118
|
# FIXME: test insensitive call with encoder
|
104
119
|
h = InsensitiveHash[{'Key with spaces' => 1}]
|
@@ -145,8 +160,8 @@ class TestInsensitiveHash < Test::Unit::TestCase
|
|
145
160
|
ih = InsensitiveHash[:a => 1, 'hello world' => 2]
|
146
161
|
ih2 = ih.send(method, :b => 2)
|
147
162
|
|
148
|
-
|
149
|
-
|
163
|
+
assert_keys [:a, 'hello world'], ih.keys
|
164
|
+
assert_keys [:a, 'hello world', :b], ih2.keys
|
150
165
|
assert ih2.has_key?('B'), 'correctly merged another hash'
|
151
166
|
|
152
167
|
assert_nil ih[:hello_world]
|
@@ -166,11 +181,13 @@ class TestInsensitiveHash < Test::Unit::TestCase
|
|
166
181
|
ih.default = nil
|
167
182
|
assert_nil ih.send(method, :b => 2)[:anything]
|
168
183
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
184
|
+
unless eight?
|
185
|
+
ih.default_proc = proc { |h, k| h[k] = :default }
|
186
|
+
mh = ih.send(method, :b => 2)
|
187
|
+
assert !mh.has_key?(:anything)
|
188
|
+
assert_equal :default, mh[:anything]
|
189
|
+
assert mh.has_key?(:anything)
|
190
|
+
end
|
174
191
|
|
175
192
|
ih2.delete 'b'
|
176
193
|
assert ih2.has_key?('B') == false
|
@@ -182,8 +199,8 @@ class TestInsensitiveHash < Test::Unit::TestCase
|
|
182
199
|
ih = InsensitiveHash[:a => 1]
|
183
200
|
ih2 = ih.send(method, :b => 2)
|
184
201
|
|
185
|
-
|
186
|
-
|
202
|
+
assert_keys [:a, :b], ih.keys
|
203
|
+
assert_keys [:a, :b], ih2.keys
|
187
204
|
assert ih2.has_key?('B'), 'correctly merged another hash'
|
188
205
|
|
189
206
|
ih2.delete 'b'
|
@@ -191,13 +208,46 @@ class TestInsensitiveHash < Test::Unit::TestCase
|
|
191
208
|
end
|
192
209
|
end
|
193
210
|
|
211
|
+
def test_merge_clash_overwritten
|
212
|
+
ih = InsensitiveHash.new
|
213
|
+
|
214
|
+
ih = ih.merge(:a => 1, :A =>2)
|
215
|
+
# No guarantee in order in 1.8
|
216
|
+
unless eight?
|
217
|
+
assert_equal 2, ih.values.first
|
218
|
+
assert_equal 2, ih['A']
|
219
|
+
end
|
220
|
+
assert_equal 1, ih.length
|
221
|
+
|
222
|
+
ih = InsensitiveHash.new
|
223
|
+
ih.underscore = true
|
224
|
+
ih.merge!(:hello_world => 1, 'hello world' =>2)
|
225
|
+
unless eight?
|
226
|
+
assert_equal 2, ih.values.first
|
227
|
+
assert_equal 2, ih[:Hello_World]
|
228
|
+
end
|
229
|
+
assert_equal 1, ih.length
|
230
|
+
end
|
231
|
+
|
194
232
|
def test_merge_clash
|
195
233
|
ih = InsensitiveHash.new
|
196
234
|
ih2 = InsensitiveHash.new
|
197
235
|
ih2.underscore = true
|
198
236
|
|
237
|
+
sih = InsensitiveHash.new
|
238
|
+
sih.safe = true
|
239
|
+
sih2 = InsensitiveHash.new
|
240
|
+
sih2.safe = true
|
241
|
+
sih2.underscore = true
|
242
|
+
|
199
243
|
[:merge, :merge!, :update, :update!].each do |method|
|
244
|
+
# No problem
|
200
245
|
[ih, ih2].each do |h|
|
246
|
+
h.send(method, { :a => 1, :A => 1, 'A' => 1})
|
247
|
+
h.send(method, { 'a' => 1, 'A' => 1 })
|
248
|
+
end
|
249
|
+
|
250
|
+
[sih, sih2].each do |h|
|
201
251
|
assert_raise(InsensitiveHash::KeyClashError) {
|
202
252
|
h.send(method, { :a => 1, :A => 1, 'A' => 1})
|
203
253
|
}
|
@@ -206,18 +256,22 @@ class TestInsensitiveHash < Test::Unit::TestCase
|
|
206
256
|
}
|
207
257
|
end
|
208
258
|
|
209
|
-
|
259
|
+
sih.send(method, { :hello_world => 1, 'hello world' => 2})
|
210
260
|
assert_raise(InsensitiveHash::KeyClashError) {
|
211
|
-
|
261
|
+
sih2.send(method, { :hello_world => 1, 'hello world' => 2})
|
212
262
|
}
|
263
|
+
ih2.send(method, { :hello_world => 1, 'hello world' => 2})
|
213
264
|
end
|
214
265
|
|
266
|
+
ih.merge({ :a => 1, :A => 1, 'A' => 1})
|
215
267
|
assert_raise(InsensitiveHash::KeyClashError) {
|
216
|
-
|
268
|
+
sih.merge({ :a => 1, :A => 1, 'A' => 1})
|
217
269
|
}
|
218
270
|
end
|
219
271
|
|
220
272
|
def test_assoc
|
273
|
+
pend "1.8" if eight?
|
274
|
+
|
221
275
|
h = InsensitiveHash[{
|
222
276
|
"colors" => ["red", "blue", "green"],
|
223
277
|
:Letters => ["a", "b", "c" ]
|
@@ -308,7 +362,7 @@ class TestInsensitiveHash < Test::Unit::TestCase
|
|
308
362
|
# FIXME: Test passes, but key_map not updated
|
309
363
|
h = InsensitiveHash[ :a => 100, :tmp_a => 200, :c => 300 ]
|
310
364
|
h.delete_if.each { |k, v| k == :tmp_a }
|
311
|
-
|
365
|
+
assert_keys [:a, :c], h.keys
|
312
366
|
end
|
313
367
|
|
314
368
|
def test_has_key_after_delete
|
@@ -316,7 +370,7 @@ class TestInsensitiveHash < Test::Unit::TestCase
|
|
316
370
|
h = InsensitiveHash[ :a => 1, :b => 2 ]
|
317
371
|
|
318
372
|
set.each { |s| assert h.has_key?(s) }
|
319
|
-
h.delete_if { |
|
373
|
+
h.delete_if { |k, v| true }
|
320
374
|
set.each { |s| assert !h.has_key?(s) }
|
321
375
|
end
|
322
376
|
|
@@ -368,11 +422,6 @@ class TestInsensitiveHash < Test::Unit::TestCase
|
|
368
422
|
assert h.underscore?
|
369
423
|
assert_equal 1, h[:hello_world]
|
370
424
|
|
371
|
-
h = InsensitiveHash.new
|
372
|
-
assert_raise(InsensitiveHash::KeyClashError) {
|
373
|
-
h.replace({ 'a' => 1, :A => 2 })
|
374
|
-
}
|
375
|
-
|
376
425
|
# TODO: FIXME
|
377
426
|
# underscore property of other
|
378
427
|
h = InsensitiveHash.new
|
@@ -389,6 +438,8 @@ class TestInsensitiveHash < Test::Unit::TestCase
|
|
389
438
|
end
|
390
439
|
|
391
440
|
def test_rassoc
|
441
|
+
pend "1.8" if eight?
|
442
|
+
|
392
443
|
a = InsensitiveHash[{1=> "one", 2 => "two", 3 => "three", "ii" => "two"}]
|
393
444
|
assert_equal [2, "two"], a.rassoc("two")
|
394
445
|
assert_nil a.rassoc("four")
|
@@ -414,7 +465,7 @@ class TestInsensitiveHash < Test::Unit::TestCase
|
|
414
465
|
end
|
415
466
|
assert_equal 3, h.fetch(:c, 3)
|
416
467
|
assert_equal 3, h.fetch(:c) { 3 }
|
417
|
-
assert_raise(KeyError) { h.fetch('D') }
|
468
|
+
assert_raise(eight? ? IndexError : KeyError) { h.fetch('D') }
|
418
469
|
end
|
419
470
|
|
420
471
|
def test_underscore
|
@@ -506,6 +557,8 @@ class TestInsensitiveHash < Test::Unit::TestCase
|
|
506
557
|
|
507
558
|
def test_underscore_clash
|
508
559
|
h = InsensitiveHash.new
|
560
|
+
h.safe = true
|
561
|
+
|
509
562
|
h['hello world'] = 1
|
510
563
|
h['HELLO_world'] = 2
|
511
564
|
assert_equal 1, h['HELLO WORLD']
|
@@ -528,7 +581,7 @@ class TestInsensitiveHash < Test::Unit::TestCase
|
|
528
581
|
h.underscore = false
|
529
582
|
h['hello world'] = 2
|
530
583
|
|
531
|
-
|
584
|
+
assert_keys [:hello_world, 'hello world'], h.keys
|
532
585
|
assert_equal 2, h['Hello World']
|
533
586
|
end
|
534
587
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: insensitive_hash
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-02-
|
12
|
+
date: 2012-02-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: test-unit
|
16
|
-
requirement: &
|
16
|
+
requirement: &2160341260 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
version: 2.3.0
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2160341260
|
25
25
|
description: Hash with case-insensitive, Symbol/String-indifferent key access
|
26
26
|
email:
|
27
27
|
- junegunn.c@gmail.com
|