tofuhash 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,159 @@
1
+ # TofuHash
2
+ #
3
+ # Links:
4
+ # * readme.txt[link:files/readme_txt.html]
5
+ # * source: http://github.com/ghouston/tofuhash/tree/master
6
+ #
7
+ # A varient of Hash which can change the lookup behavior of keys.
8
+ # The default TofuHash will match Symbol and String without reguard
9
+ # to case. By subclassing TofuKey, this behavior can be changed.
10
+ #
11
+ #
12
+ # License:
13
+ #
14
+ # (The MIT License + Free Software Foundation Advertising Prohibition)
15
+ #
16
+ # Copyright (c) 2007 Gregory N. Houston
17
+ #
18
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
19
+ # of this software and associated documentation files (the "Software"), to deal
20
+ # in the Software without restriction, including without limitation the rights
21
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22
+ # copies of the Software, and to permit persons to whom the Software is
23
+ # furnished to do so, subject to the following conditions:
24
+ #
25
+ # The above copyright notice and this permission notice shall be included in
26
+ # all copies or substantial portions of the Software.
27
+ #
28
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
33
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
34
+ # THE SOFTWARE.
35
+ #
36
+ # Except as contained in this notice, the name(s) of the above copyright holders
37
+ # shall not be used in advertising or otherwise to promote the sale, use or other
38
+ # dealings in this Software without prior written authorization.
39
+ #
40
+ class TofuHash < Hash
41
+ module Version
42
+ MAJOR = 0
43
+ MINOR = 1
44
+ REVISION = 0
45
+ STRING = [MAJOR, MINOR, REVISION].join('.')
46
+ end
47
+
48
+ # see Hash.new
49
+ def initialize ( default = nil )
50
+ if block_given?
51
+ if default
52
+ raise ArgumentError, "Can't initialize Hash with both a default value and a block"
53
+ end
54
+ super() { |hash,key| yield(hash, decode(key)) }
55
+ else
56
+ super
57
+ end
58
+ end
59
+
60
+ # see Hash#encode
61
+ def encode( key )
62
+ TofuKey.new(key)
63
+ end
64
+
65
+ # see Hash#decode
66
+ def decode( key )
67
+ key.decode
68
+ end
69
+
70
+ class << self
71
+ # see Hash.[]
72
+ def [](*args)
73
+ if args.size == 1 && args[0].instance_of?( Object::Hash )
74
+ h = TofuHash.new
75
+ args[0].each { |k,v| h.store( k,v ) }
76
+ h
77
+ elsif (args.size % 2 != 0)
78
+ raise ArgumentError, "odd number of arguments for TofuHash"
79
+ else
80
+ h = TofuHash.new
81
+ 1.step( args.size, 2 ) { |i| h.store(args[i-1],args[i]) }
82
+ h
83
+ end
84
+ end
85
+ end
86
+
87
+ # see Hash#[]=
88
+ def []= key,value
89
+ super( encode(key), value )
90
+ end
91
+
92
+ alias :regular_each :each unless method_defined?(:regular_each)
93
+
94
+ # see Hash#each
95
+ def each &block
96
+ self.regular_each do |key, value|
97
+ block.call( decode(key), value )
98
+ end
99
+ end
100
+
101
+ # see Hash#store
102
+ def store key, value
103
+ super( encode(key), value )
104
+ end
105
+
106
+ # see Hash#[]
107
+ def [] key
108
+ super( encode(key) )
109
+ end
110
+
111
+ # see Hash#has_key?
112
+ def has_key? key
113
+ super( encode(key) )
114
+ end
115
+
116
+ # see Hash#keys
117
+ def keys
118
+ # collect will call each which decodes the key
119
+ self.collect { |k,v| k }
120
+ end
121
+
122
+ alias_method :regular_inspect, :inspect unless method_defined?(:regular_inspect)
123
+
124
+ # see Hash#values_at
125
+ def values_at( *args )
126
+ values = Array.new
127
+ args.each { |key| values << self[key] }
128
+ values
129
+ end
130
+
131
+ # see Hash#to_a
132
+ def to_a
133
+ aux = []
134
+ self.each do |key,value|
135
+ aux << [ key, value ]
136
+ end
137
+ aux
138
+ end
139
+
140
+ # see Hash#include?
141
+ def include?(key)
142
+ super(encode(key))
143
+ end
144
+
145
+ alias :regular_delete_if :delete_if
146
+
147
+ # see Hash#delete_if
148
+ def delete_if(&block)
149
+ self.regular_delete_if do |key, value|
150
+ block.call( decode(key), value)
151
+ end
152
+ end
153
+
154
+ # Deletes every key-value pair for which block evaluates to false.
155
+ def delete_unless #:yield:
156
+ delete_if{ |key, value| ! yield(key, value) }
157
+ end
158
+
159
+ end # class TofuHash
@@ -0,0 +1,90 @@
1
+ # TofuKey
2
+ #
3
+ # Links:
4
+ # * readme.txt[link:files/readme_txt.html]
5
+ # * source: http://github.com/ghouston/tofuhash/tree/master
6
+ #
7
+ # For use with TofuHash. A wrapper for the key of a Hash which will alter the behavior of keys.
8
+ # The behavior provided by default is case-insensitive, and indifferent access for strings and symbols.
9
+ # By subclassing TofuHash, you can create your own behavior.
10
+ #
11
+ # License:
12
+ #
13
+ # (The MIT License + Free Software Foundation Advertising Prohibition)
14
+ #
15
+ # Copyright (c) 2007 Gregory N. Houston
16
+ #
17
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
18
+ # of this software and associated documentation files (the "Software"), to deal
19
+ # in the Software without restriction, including without limitation the rights
20
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21
+ # copies of the Software, and to permit persons to whom the Software is
22
+ # furnished to do so, subject to the following conditions:
23
+ #
24
+ # The above copyright notice and this permission notice shall be included in
25
+ # all copies or substantial portions of the Software.
26
+ #
27
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
33
+ # THE SOFTWARE.
34
+ #
35
+ # Except as contained in this notice, the name(s) of the above copyright holders
36
+ # shall not be used in advertising or otherwise to promote the sale, use or other
37
+ # dealings in this Software without prior written authorization.
38
+ #
39
+ class TofuKey
40
+ attr_reader :original_key, :coded_key
41
+
42
+ # preserve the key (Strings are cloned and frozen just like Hash's behavior); then encodes the key for fast comparison
43
+ def initialize( key )
44
+ if key.instance_of? String
45
+ @original_key = key.clone.freeze
46
+ else
47
+ @original_key = key
48
+ end
49
+ encode
50
+ end
51
+
52
+ # stores a @coded_key which is used for quick comparison and as the hash key. the default encoding will
53
+ # convert Symbols to downcased strings; anything responding to downcase is converted via downcase.
54
+ def encode
55
+ if @original_key.instance_of? Symbol
56
+ @coded_key = @original_key.to_s.downcase
57
+ elsif @original_key.respond_to? :downcase
58
+ @coded_key = @original_key.downcase
59
+ else
60
+ @coded_key = @original_key
61
+ end
62
+ end
63
+
64
+ # returns the preserved key
65
+ def decode
66
+ @original_key
67
+ end
68
+
69
+ # get the hash of the key, which calls #hash on the encoded key.
70
+ def hash
71
+ @coded_key.hash
72
+ end
73
+
74
+ # compares the encoded key to another object.
75
+ #
76
+ # given symbols are converted to downcase strings before comparison.
77
+ # given objects which respond to downcase are downcased before comparison.
78
+ # given TofuKey will compare the encoded keys.
79
+ def eql? obj
80
+ if obj.instance_of? Symbol
81
+ @coded_key.eql?( obj.to_s.downcase )
82
+ elsif obj.instance_of? TofuKey
83
+ @coded_key.eql?( obj.coded_key )
84
+ elsif obj.respond_to? :downcase
85
+ @coded_key.eql?( obj.downcase )
86
+ else
87
+ @coded_key.eql?( obj )
88
+ end
89
+ end
90
+ end
data/lib/tofuhash.rb ADDED
@@ -0,0 +1,44 @@
1
+ # TofuHash
2
+ #
3
+ # Links:
4
+ # * readme.txt[link:files/readme_txt.html]
5
+ # * source: http://github.com/ghouston/tofuhash/tree/master
6
+ #
7
+ # A varient of Hash which can change the lookup behavior of keys.
8
+ # The default TofuHash will match Symbol and String without reguard
9
+ # to case. By subclassing TofuKey, this behavior can be changed.
10
+ #
11
+ # License:
12
+ #
13
+ # (The MIT License + Free Software Foundation Advertising Prohibition)
14
+ #
15
+ # Copyright (c) 2007 Gregory N. Houston
16
+ #
17
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
18
+ # of this software and associated documentation files (the "Software"), to deal
19
+ # in the Software without restriction, including without limitation the rights
20
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21
+ # copies of the Software, and to permit persons to whom the Software is
22
+ # furnished to do so, subject to the following conditions:
23
+ #
24
+ # The above copyright notice and this permission notice shall be included in
25
+ # all copies or substantial portions of the Software.
26
+ #
27
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
33
+ # THE SOFTWARE.
34
+ #
35
+ # Except as contained in this notice, the name(s) of the above copyright holders
36
+ # shall not be used in advertising or otherwise to promote the sale, use or other
37
+ # dealings in this Software without prior written authorization.
38
+ #
39
+ unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
40
+ $:.unshift(File.expand_path(File.dirname(__FILE__)))
41
+ end
42
+
43
+ require 'tofuhash/tofukey'
44
+ require 'tofuhash/tofuhash'
data/readme.txt ADDED
@@ -0,0 +1,100 @@
1
+ = TofuHash
2
+ by Gregory N. Houston
3
+
4
+ TofuHash makes it possible to use a Hash without having to
5
+ worry about the differences between using String, Symbol,
6
+ uppercase and downcase for the keys.
7
+ TofuHash is both a case-insensitive Hash, and indifferent
8
+ to access by String or Symbol.
9
+
10
+ for Example:
11
+
12
+ require 'tofuhash'
13
+ h = TofuHash[ :aSymbol => "symbol", "MixedCaseString" => "string", 11 => "number" ]
14
+ puts h["asymbol"] #=> "symbol"
15
+ puts h[:mixedCaseString] #=> "string"
16
+ puts h[11] #=> "number"
17
+
18
+ Version:: 0.1.0 A useful and well tested subset of Hash methods is available.
19
+
20
+ Tested to work with:
21
+ Ruby 1.8.6
22
+ Ruby 1.9.1
23
+
24
+ How is TofuHash differenct than Hash?
25
+ * TofuHash wraps the key into a TofuKey which is used internally inside TofuHash.
26
+ The TofuKey defines new behavior for handling the key. By
27
+ default it will treat Symbol, String, and uppercase vs downcase as the same. This
28
+ behavior can be changed by creating TofuHash and providing an alternative
29
+ version of TofuKey.
30
+
31
+ * TofuHash adds the method TofuHash#delete_unless
32
+
33
+ == Links:
34
+
35
+ Start Here:: http://tofuhash.rubyforge.org
36
+
37
+ Project:: http://rubyforge.org/projects/tofuhash
38
+ Documents:: http://tofuhash.rubyforge.org
39
+ RubyGems:: Install with: <b>gem install tofuhash</b>
40
+ Download:: Download from RubyForge at http://rubyforge.org/projects/tofuhash/
41
+ Authors Blog:: http://ghouston.blogspot.com
42
+ Browse Source:: link:rcov/index.html
43
+ Source code is hosted on Github at: http://github.com/ghouston/tofuhash/tree/master
44
+
45
+ == LICENSE:
46
+
47
+ (The MIT License + Free Software Foundation Advertising Prohibition)
48
+
49
+ Copyright (c) 2007 Gregory N. Houston
50
+
51
+ Permission is hereby granted, free of charge, to any person obtaining a copy
52
+ of this software and associated documentation files (the "Software"), to deal
53
+ in the Software without restriction, including without limitation the rights
54
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
55
+ copies of the Software, and to permit persons to whom the Software is
56
+ furnished to do so, subject to the following conditions:
57
+
58
+ The above copyright notice and this permission notice shall be included in
59
+ all copies or substantial portions of the Software.
60
+
61
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
62
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
63
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
64
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
65
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
66
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
67
+ THE SOFTWARE.
68
+
69
+ Except as contained in this notice, the name(s) of the above copyright holders
70
+ shall not be used in advertising or otherwise to promote the sale, use or other
71
+ dealings in this Software without prior written authorization.
72
+
73
+ The file test-tofuhash.rb is released under the Ruby License since it
74
+ contains source code based on Ruby's released source.
75
+
76
+ == Credits:
77
+
78
+ Inspired by:
79
+ * http://pastie.caboo.se/154304 and used with Stefan Rusterholz's permission;
80
+ * HashWithIndifferentAccess in Rail's ActiveSupport.
81
+
82
+ Contributors:
83
+ * Greg Houston (http://ghouston.blogspot.com) original release and project maintainer
84
+ * Nacho Caballero (http://github.com/nachocab/) added #to_a, #delete_if, #delete_unless, #include?
85
+
86
+ == Release History:
87
+
88
+ Feb 28 2009 - 0.1.0 release on rubyforge. Added gem, rdoc, rcov output.
89
+ Added TofuHash::Version module
90
+
91
+ Feb 15 2009 - 0.0.2 released on git hub. Merged in pull request from
92
+ http://github.com/nachocab/tofuhash/tree/master [Thanks nachocab!]
93
+ nachocab added to_a, delete_if, delete_unless, include? methods. nachocab also
94
+ updated the exception raised when TofuHash#initialize is called with both
95
+ a default value and default block. It now raises "wrong number of arguments"
96
+ which matches the behavior of Hash. I (ghouston) tweaked the test cases to match
97
+ the examples from Hash's ri documentation.
98
+
99
+ Dec 12 2008 - 0.0.1 released on git hub. Working solution, only more complete
100
+ testing is needed. Know issues: a) Hash doesn't know how to compare with TofuHash.
@@ -0,0 +1,285 @@
1
+ require 'test/unit'
2
+ require 'pp'
3
+ require 'lib/tofuhash'
4
+
5
+ =begin rdoc
6
+ test-tofuhash.rb
7
+
8
+ Test cases for TofuHash. This includes modified versions of Ruby's unit tests
9
+ for Hash, and Ruby's Hash examples in the ri documentation. Plus some custom
10
+ tests to validate similarities between Hash and TofuHash.
11
+
12
+ Version: see readme.txt for details.
13
+
14
+ License:
15
+
16
+ tofuhash.rb is released under the MIT License + Free Software Foundation
17
+ Advertising Prohibition. see readme.txt file for details.
18
+
19
+ test-tofuhash.rb (this file) is released under the Ruby License since it
20
+ contains source code based on Ruby's released source.
21
+ =end
22
+
23
+ module TofuHashTesting
24
+ class Test_TofuHash < Test::Unit::TestCase
25
+ def test_new
26
+ assert_raise ArgumentError do
27
+ h = TofuHash.new( :default ) { |hash,key| key }
28
+ end
29
+
30
+ h = TofuHash.new
31
+ assert_equal( 0, h.size )
32
+ assert_equal( nil, h[:missing] )
33
+
34
+ h = TofuHash.new( :default )
35
+ assert_equal( 0, h.size )
36
+ assert_equal( :default, h[:missing] )
37
+
38
+ h = TofuHash.new do |hash,key|
39
+ assert_equal( :missing, key )
40
+ assert_same( h, hash )
41
+ hash[key] = :default_block
42
+ end
43
+ assert_equal( 0, h.size )
44
+ assert_equal( :default_block, h[:missing] )
45
+ assert_equal( 1, h.size )
46
+ assert_equal( [:missing], h.keys )
47
+ assert_equal( [:default_block], h.values )
48
+ end
49
+
50
+ def test_values_at
51
+ h = TofuHash[21=>22,22=>24,23=>26,24=>28]
52
+ assert_equal([24,26], h.values_at( 22, 23 ))
53
+ end
54
+
55
+ def test_keys
56
+ h = TofuHash["Alpha"=>2,:betA=>4,"gAmmA"=>6]
57
+ assert_equal( ["Alpha",:betA,"gAmmA"], h.keys.sort { |a,b| a.to_s <=> b.to_s } )
58
+ end
59
+
60
+ def test_square_bracket_initializer
61
+ h = TofuHash[:a=>:b, :c=>:d]
62
+ assert_equal( TofuHash, h.class )
63
+ assert_equal( :b, h[:a] )
64
+ assert_equal( :d, h[:c] )
65
+ assert_equal( 2, h.size )
66
+
67
+ assert_raise ArgumentError do
68
+ h = TofuHash[1,2,3]
69
+ end
70
+
71
+ h = TofuHash[:happy, :sad, :rich, :poor]
72
+ assert_equal( TofuHash, h.class )
73
+ assert_equal( :sad, h[:happy] )
74
+ assert_equal( :poor, h[:rich] )
75
+ assert_equal( 2, h.size )
76
+ h = TofuHash[]
77
+ assert_equal( 0, h.size )
78
+ end
79
+
80
+ def test_store
81
+ h = TofuHash.new
82
+ h.store('Alpha',1)
83
+ h.store(1,'ALPHA')
84
+ assert_equal( 1, h['AlPhA'] )
85
+ assert_equal( 'ALPHA', h[1] )
86
+
87
+ h['Beta']=2
88
+ h[2] = 'Beta'
89
+ assert_equal( 2, h['bEtA'] )
90
+ assert_equal( 'Beta', h[2] )
91
+
92
+ h[:Gamma]=3
93
+ h[3] = 'Gamma'
94
+ assert_equal( 3, h[:Gamma] )
95
+ assert_equal( 3, h['Gamma'] )
96
+ assert_equal( 3, h['gAmMA'] )
97
+ assert_equal( 3, h[:gAMMA] )
98
+ end
99
+
100
+ def test_each
101
+ h = TofuHash[15,16, 11,12, 19,20, 17,18, 13,14]
102
+ h.each { |k,v| assert_equal( k+1, v ) }
103
+ end
104
+ end # class Test_TofuHash
105
+
106
+ # copied from /ruby/src/ruby-1.8.6/test/ruby/test_hash.rb
107
+ # modified to use TofuHash instead of Hash
108
+ class TestHash < Test::Unit::TestCase
109
+ def test_hash
110
+ x = TofuHash[1=>2, 2=>4, 3=>6]
111
+ y = TofuHash[1, 2, 2, 4, 3, 6]
112
+ assert_equal(2, x[1])
113
+
114
+ assert(begin
115
+ for k,v in y
116
+ raise if k*2 != v
117
+ end
118
+ true
119
+ rescue
120
+ false
121
+ end)
122
+
123
+ assert_equal(3, x.length)
124
+ assert(x.has_key?(1))
125
+ assert(x.has_value?(4))
126
+ assert_equal([4,6], x.values_at(2,3))
127
+ assert_equal(TofuHash[1=>2, 2=>4, 3=>6], x)
128
+
129
+ z = y.keys.join(":")
130
+ assert_equal("1:2:3", z)
131
+
132
+ z = y.values.join(":")
133
+ assert_equal("2:4:6", z)
134
+ assert_equal(x, y)
135
+
136
+ y.shift
137
+ assert_equal(2, y.length)
138
+
139
+ z = [1,2]
140
+ y[z] = 256
141
+ assert_equal(256, y[z])
142
+
143
+ x = TofuHash.new(0)
144
+ x[1] = 1
145
+ assert_equal(1, x[1])
146
+ assert_equal(0, x[2])
147
+
148
+ x = TofuHash.new([])
149
+ assert_equal([], x[22])
150
+ assert_same(x[22], x[22])
151
+
152
+ x = TofuHash.new{[]}
153
+ assert_equal([], x[22])
154
+ assert_not_same(x[22], x[22])
155
+
156
+ x = TofuHash.new{|h,k| z = k; h[k] = k*2}
157
+ z = 0
158
+ assert_equal(44, x[22])
159
+ assert_equal(22, z)
160
+ z = 0
161
+ assert_equal(44, x[22])
162
+ assert_equal(0, z)
163
+ x.default = 5
164
+ assert_equal(5, x[23])
165
+
166
+ x = TofuHash.new
167
+ def x.default(k)
168
+ k = decode(k)
169
+ $z = k
170
+ self[k] = k*2
171
+ end
172
+ $z = 0
173
+ assert_equal(44, x[22])
174
+ assert_equal(22, $z)
175
+ $z = 0
176
+ assert_equal(44, x[22])
177
+ assert_equal(0, $z)
178
+ end
179
+
180
+ class MyClass
181
+ attr_reader :str
182
+ def initialize(str)
183
+ @str = str
184
+ end
185
+ def eql?(o)
186
+ o.is_a?(MyClass) && str == o.str
187
+ end
188
+ def hash
189
+ @str.hash
190
+ end
191
+ end
192
+
193
+ def test_ri_hash_code
194
+ a = MyClass.new("some string")
195
+ b = MyClass.new("some string")
196
+ assert( a.eql?( b ) ) #=> true
197
+
198
+ h = TofuHash.new #was: h={}
199
+
200
+ h[a] = 1
201
+ assert_equal( h[a],1 ) #=> 1
202
+ assert_equal( h[b],1 ) #=> 1
203
+
204
+ h[b] = 2
205
+ assert_equal( h[a],2 ) #=> 2
206
+ assert_equal( h[b],2 ) #=> 2
207
+ end
208
+
209
+ def test_ri_hash_new_code
210
+ h = TofuHash.new("Go Fish")
211
+ h["a"] = 100
212
+ h["b"] = 200
213
+ assert_equal( h["a"], 100 ) #=> 100
214
+ assert_equal( h["c"], "Go Fish" ) #=> "Go Fish"
215
+ # The following alters the single default object
216
+ assert_equal( h["c"].upcase!, "GO FISH" ) #=> "GO FISH"
217
+ assert_equal( h["d"], "GO FISH" ) #=> "GO FISH"
218
+ assert_equal( h.keys, ["a","b"] ) #=> ["a", "b"]
219
+
220
+ # While this creates a new default object each time
221
+ h = TofuHash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
222
+ assert_equal( h["c"], "Go Fish: c" ) #=> "Go Fish: c"
223
+ assert_equal( h["c"].upcase!, "GO FISH: C" ) #=> "GO FISH: C"
224
+ assert_equal( h["d"], "Go Fish: d" ) #=> "Go Fish: d"
225
+ assert_equal( h.keys, ["c","d"] ) #=> ["c", "d"]
226
+ end
227
+
228
+ def test_ri_hash_square_bracket_code
229
+ assert_equal( TofuHash["a", 100, "b", 200], {"a"=>100, "b"=>200} ) #=> {"a"=>100, "b"=>200}
230
+ assert_equal( TofuHash["a" => 100, "b" => 200], {"a"=>100, "b"=>200} ) #=> {"a"=>100, "b"=>200}
231
+ end
232
+
233
+ def test_to_a
234
+ hash = TofuHash["a" => 2, "b" => 1]
235
+ assert_equal [["a",2],["b",1]], hash.to_a
236
+ end
237
+
238
+ def test_ri_to_a
239
+ h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300 }
240
+ result = h.to_a
241
+ sorted = h.to_a.sort { |a,b| a[0] <=> b[0] }
242
+ assert_equal( [['a',100],['c',300],['d',400]], sorted )
243
+ end
244
+
245
+ def test_include?
246
+ hash = TofuHash["a" => 2, "b" => 1]
247
+ assert( hash.include?( 'a' ))
248
+ end
249
+
250
+ def test_ri_include?
251
+ h = { "a" => 100, "b" => 200 }
252
+ assert( h.has_key?("a") )
253
+ assert_equal( false, h.has_key?("z"))
254
+ end
255
+
256
+ def test_ri_delete_if
257
+ h = TofuHash["a" => 100, "b" => 200, "c" => 300]
258
+ h.delete_if { |key,value| key >= 'b' }
259
+ assert_equal TofuHash['a' => 100], h
260
+ end
261
+
262
+ def test_delete_unless
263
+ hash = TofuHash["a" => 2, "b" => 1]
264
+ hash.delete_unless { |k,v| k == 'b' }
265
+ assert_equal TofuHash['b' => 1], hash
266
+ end
267
+
268
+ def test_ri_hash_equality
269
+ =begin
270
+ TODO: KNOWN ISSUE, Hash doesn't know how to compare to TofuHash.
271
+
272
+ h1 = TofuHash[ "a" => 1, "c" => 2 ]
273
+ h2 = { 7 => 35, "c" => 2, "a" => 1 }
274
+ h3 = TofuHash[ "a" => 1, "c" => 2, 7 => 35 ]
275
+ h4 = TofuHash[ "a" => 1, "d" => 2, "f" => 35 ]
276
+ puts "h1"
277
+ assert_equal( h1 == h2, false ) #=> false
278
+ puts "h2"
279
+ assert_equal( h2 == h3, true ) #=>
280
+ puts "h3"
281
+ assert_equal( h3 == h4, false ) #=> false
282
+ =end
283
+ end
284
+ end # class TestHash
285
+ end # module TofuHash
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4
3
+ specification_version: 1
4
+ name: tofuhash
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.1.0
7
+ date: 2009-02-28 00:00:00 -06:00
8
+ summary: TofuHash, a Hash that is case-insensitive and treats symbols and strings as equals (customizable); always preserving the original key.
9
+ require_paths:
10
+ - lib
11
+ email:
12
+ homepage: http://tofuhash.rubyforge.org/
13
+ rubyforge_project: tofuhash
14
+ description: TofuHash, a Hash that is case-insensitive and treats symbols and strings as equals (customizable); always preserving the original key.
15
+ autorequire: tofuhash
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Gregory N. Houston
31
+ files:
32
+ - lib/tofuhash/tofuhash.rb
33
+ - lib/tofuhash/tofukey.rb
34
+ - lib/tofuhash.rb
35
+ - test/test-tofuhash.rb
36
+ - readme.txt
37
+ test_files:
38
+ - test/test-tofuhash.rb
39
+ rdoc_options:
40
+ - --main
41
+ - readme.txt
42
+ - --title
43
+ - TofuHash (rdoc)
44
+ extra_rdoc_files:
45
+ - readme.txt
46
+ executables: []
47
+
48
+ extensions: []
49
+
50
+ requirements: []
51
+
52
+ dependencies: []
53
+