tofuhash 0.1.0

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.
@@ -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
+