Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save lhm/1014457 to your computer and use it in GitHub Desktop.
Save lhm/1014457 to your computer and use it in GitHub Desktop.
ruby spec and rubinius patch to allow object as hash key with protected hash method
From 510cbee3d1414cd4c5318ac135250e2e726bb593 Mon Sep 17 00:00:00 2001
From: Lars Henrik Mai <lars.mai@kontinui.de>
Date: Wed, 8 Jun 2011 14:29:37 +0200
Subject: [PATCH 1/2] Updated Hash constructor_spec to test for method visibility of hash
method when a key is an object
---
spec/ruby/core/hash/constructor_spec.rb | 9 +++++++++
spec/ruby/core/hash/fixtures/classes.rb | 6 ++++++
2 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/spec/ruby/core/hash/constructor_spec.rb b/spec/ruby/core/hash/constructor_spec.rb
index d8c2d2f..14b35a1 100644
--- a/spec/ruby/core/hash/constructor_spec.rb
+++ b/spec/ruby/core/hash/constructor_spec.rb
@@ -49,4 +49,13 @@ describe "Hash.[]" do
hash_class[MyHash[1, 2]].class.should == hash_class
MyHash[hash_class[1, 2]].should be_kind_of(MyHash)
end
+
+ it "ignores hash method visibility when key is an object" do
+ [:protected, :private].each do |v|
+ ObjectAsKey.send(v, :hash)
+ obj = ObjectAsKey.new
+ lambda { hash_class[obj,1] }.should_not raise_error(NoMethodError)
+ end
+ end
+
end
diff --git a/spec/ruby/core/hash/fixtures/classes.rb b/spec/ruby/core/hash/fixtures/classes.rb
index 5d13ed6..d8bb54f 100644
--- a/spec/ruby/core/hash/fixtures/classes.rb
+++ b/spec/ruby/core/hash/fixtures/classes.rb
@@ -20,6 +20,12 @@ class ToHashHash < hash_class
end
end
+class ObjectAsKey
+ def hash
+ 123456789
+ end
+end
+
module HashSpecs
def self.empty_frozen_hash
@empty ||= new_hash
--
1.6.6
From 2939a54df31d2dad037362010977d6fa9db7439c Mon Sep 17 00:00:00 2001
From: Lars Henrik Mai <lars.mai@kontinui.de>
Date: Wed, 8 Jun 2011 15:31:41 +0200
Subject: [PATCH 2/2] Allow Hash[]= to work with objects as keys regardless of #hash method visibility
---
kernel/common/hash.rb | 15 +++++++++++++--
1 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/kernel/common/hash.rb b/kernel/common/hash.rb
index 4b3106d..345ce21 100644
--- a/kernel/common/hash.rb
+++ b/kernel/common/hash.rb
@@ -205,7 +205,7 @@ class Hash
redistribute @entries if @size > @max_entries
- key_hash = key.hash
+ key_hash = get_hash(key)
index = key_hash & @mask
entry = @entries[index]
@@ -377,7 +377,7 @@ class Hash
# Searches for an entry matching +key+. Returns the entry
# if found. Otherwise returns +nil+.
def find_entry(key)
- key_hash = key.hash
+ key_hash = get_hash(key)
entry = @entries[key_index(key_hash)]
while entry
@@ -388,6 +388,17 @@ class Hash
end
end
+ # get the hash of the key even if protected or private, but display a warning
+ def get_hash(key)
+ begin
+ key.hash
+ rescue(NoMethodError)
+ warn "calling protected or private method #{key.class}#hash on object #{key}, should be public"
+ key.__send__(:hash)
+ end
+ end
+ private :get_hash
+
def index(value)
each_entry do |entry|
return entry.key if entry.value == value
--
1.6.6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment