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
         |