# Help extending Hash to allow hexadecimal encoded keys (problem with "Delegator")

**URL:** <https://www.ruby-forum.com/t/help-extending-hash-to-allow-hexadecimal-encoded-keys-problem-with-delegator/138467>\
**Category:** Ruby\
**Created:** [May 23, 2008, 10:19am UTC](https://www.ruby-forum.com/t/help-extending-hash-to-allow-hexadecimal-encoded-keys-problem-with-delegator/138467 "2008-05-23T10:19:40Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![ISSSSaki\_Baz\_C](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/51bf81/32.png) [@ISSSSaki\_Baz\_C](https://www.ruby-forum.com/u/ISSSSaki_Baz_C)\
**Post date:** [May 23, 2008, 10:19am UTC](https://www.ruby-forum.com/t/help-extending-hash-to-allow-hexadecimal-encoded-keys-problem-with-delegator/138467/1 "2008-05-23T10:19:40Z")

</div>

Hi, basically I need to implement a Hash in which keys can be encoded  
with “pseudo” hexadecimal. This is basically to store URI parameters  
and headers (defined in RFC 2396), so:

“tag” == “t%61g”  
“alice” == “%61l%69ce”

I’m implementing a UriParametersHash using “Derivate” (thanks to Robert  
Klemme):

* * *

require ‘delegate’  
class UriParametersHash \< DelegateClass(Hash)

```
CiString = Struct.new :string do

  def unescape(string)
    eval %{ "#{ string.gsub(/%/,'\x') }" }
  end
  private :unescape

  def to_s
    string.downcase
  end

  def hash
    unescape(string.downcase).hash
  end

  def eql?(s)
    unescape(string.downcase).eql? unescape(s.string.downcase)
  end
  alias == eql?

  def inspect; string.inspect; end

end # CiString

def initialize
  super({})
end

attr_accessor :modified

def []=(k,v)
  k = CiString.new(k) if String === k
  __getobj__ [k] = v
end

def [](k)
  k = CiString.new(k) if String === k
end

```

## end # class UriParametersHash

It works ok:

@uri  
=\> {“a”=\>123, “T%61g”=\>“lalala”}

@uri[“tag”]  
=\> “lalala”

@uri[“T%61G”] = “lololo”  
=\> “lololo”

But I need to implement other Hash methods as “delete”, “find”,  
“find\_all”… and I get into problems: For example I define “find” in  
this way:

```
def find()
  k = CiString.new(k) if String === k
  __getobj__"find" (k)
end

```

But it gives me an error:

@uri.find{|e| e[0]==“tag”}  
ArgumentError: wrong number of arguments (1 for 0)  
from uri.rb:100:in ` __getobj__' from uri.rb:100:in `find’

Unfortunatelly I don’t find good documentation to handle  
\_\_getobj\_\_method, could somebody give me a tip please? Thanks a lot.

- 

IÃ±aki Baz C.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![ISSSSaki\_Baz\_C](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/51bf81/32.png) [@ISSSSaki\_Baz\_C](https://www.ruby-forum.com/u/ISSSSaki_Baz_C)\
**Post date:** [May 23, 2008, 11:16am UTC](https://www.ruby-forum.com/t/help-extending-hash-to-allow-hexadecimal-encoded-keys-problem-with-delegator/138467/2 "2008-05-23T11:16:44Z")

</div>

Hi,

2008/5/23 IÃ±aki Baz C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> ```
> require 'delegate'
> string.downcase
> 
> def []=(k,v)
> 
> ```
> 
> =\> “lololo”
> 
> \_\_getobj\_\_method, could somebody give me a tip please? Thanks a lot.

Here is a modified version including find and find\_all:

```
   require 'delegate'
   class UriParametersHash < DelegateClass(Hash)

           CiString = Struct.new :string do

                   def unescape(string)
                           eval %{ "#{ string.gsub(/%/,'\x') }" }
                   end
                   private :unescape

                   def to_s
                           string.downcase
                   end

                   def hash
                           unescape(string.downcase).hash
                   end

                   def eql?(s)
                            s = CiString.new(s) if String === s
                           unescape(string.downcase).eql?

```

unescape(s.string.downcase)  
end  
alias == eql?

```
                   def inspect; string.inspect; end

           end # CiString

           def initialize
                   super({})
           end

           attr_accessor :modified

           def []=(k,v)
                   k = CiString.new(k) if String === k
                   __getobj__ [k] = v
           end

           def [](k)
                   k = CiString.new(k) if String === k
                   __getobj__ [k]
           end

           def find(ifnone = nil,&blk)
             __getobj__.find(ifnone,&blk)
           end

           def find_all(&blk)
             __getobj__.find_all(&blk)
           end
   end # class UriParametersHash

```

Regards,

Park H.

---

<div class="post-metadata">

**Author:** ![ISSSSaki\_Baz\_C](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/51bf81/32.png) [@ISSSSaki\_Baz\_C](https://www.ruby-forum.com/u/ISSSSaki_Baz_C)\
**Post date:** [May 23, 2008, 12:22pm UTC](https://www.ruby-forum.com/t/help-extending-hash-to-allow-hexadecimal-encoded-keys-problem-with-delegator/138467/3 "2008-05-23T12:22:36Z")

</div>

2008/5/23, Heesob P. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> ```
> def find(ifnone = nil,&blk)
> __getobj__.find(ifnone,&blk)
> end
> 
> def find_all(&blk)
> __getobj__.find_all(&blk)
> end
> 
> ```

Thanks a lot, but it gives me errors:

@uri  
=\> {“T%61g”=\>“%61liCE”, “qwe”=\>“qqqqqqqqqqQQQQQQQQQQQ”}

@uri.find {|e| e[0] == “qwe” }  
NoMethodError: undefined method `string' for "qwe":String from uri.rb:72:in `==’  
from (irb):6  
from (irb):6:in `find' from uri.rb:98:in `each’  
from uri.rb:98:in `find' from uri.rb:98:in `find’  
from (irb):6

Unfortunatelly I have no idea of how to debug it since I don’t  
understand how exactly Delegator works. Any tip please?

Really thanks a lot.

---

<div class="post-metadata">

**Author:** ![ISSSSaki\_Baz\_C](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/51bf81/32.png) [@ISSSSaki\_Baz\_C](https://www.ruby-forum.com/u/ISSSSaki_Baz_C)\
**Post date:** [May 23, 2008, 3:10pm UTC](https://www.ruby-forum.com/t/help-extending-hash-to-allow-hexadecimal-encoded-keys-problem-with-delegator/138467/4 "2008-05-23T15:10:40Z")

</div>

Hi,

2008/5/23 IÃ±aki Baz C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> > ```
> > __getobj__ [k]
> > 
> > ```
> 
> ```
> from (irb):6:in `find'
> from uri.rb:98:in `each'
> from uri.rb:98:in `find'
> from uri.rb:98:in `find'
> from (irb):6
> 
> ```
> 
> Unfortunatelly I have no idea of how to debug it since I don’t  
> understand how exactly Delegator works. Any tip please?

I guess you did not try my code.  
I have modified eql? like this:

def eql?(s)  
s = CiString.new(s) if String === s  
unescape(string.downcase).eql? unescape(s.string.downcase)  
end

Regards,

Park H.

---

<div class="post-metadata">

**Author:** ![ISSSSaki\_Baz\_C](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/51bf81/32.png) [@ISSSSaki\_Baz\_C](https://www.ruby-forum.com/u/ISSSSaki_Baz_C)\
**Post date:** [May 26, 2008, 10:24am UTC](https://www.ruby-forum.com/t/help-extending-hash-to-allow-hexadecimal-encoded-keys-problem-with-delegator/138467/5 "2008-05-26T10:24:12Z")

</div>

2008/5/23, Heesob P. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> Hi,

> I guess you did not try my code.  
> I have modified eql? like this:
> 
> def eql?(s)  
> s = CiString.new(s) if String === s  
> unescape(string.downcase).eql? unescape(s.string.downcase)  
> end

Thanks both. I tryed the wrong code, I’ll try now what you suggest.  
Thanks a lot.

---

<div class="post-metadata">

**Author:** ![ISSSSaki\_Baz\_C](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/51bf81/32.png) [@ISSSSaki\_Baz\_C](https://www.ruby-forum.com/u/ISSSSaki_Baz_C)\
**Post date:** [May 23, 2008, 3:09pm UTC](https://www.ruby-forum.com/t/help-extending-hash-to-allow-hexadecimal-encoded-keys-problem-with-delegator/138467/6 "2008-05-23T15:09:29Z")

</div>

On Fri, May 23, 2008 at 11:21 AM, Iñaki Baz C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > ```
> > __getobj__ [k]
> > 
> > ```
> 
> ```
> from (irb):6:in `find'
> 
> ```
> 
> –  
> Iñaki Baz C.  
> [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

I think you want something like:

```
def eql?(s)
  unescape(string.downcase).eql? unescape(s.to_s.downcase)
end

```

with Park’s changes so that:

uri = UriParametersHash.new  
uri[“T%61G”] = “lololo”  
uri # =\> {“T%61G”=\>“lololo”}  
uri.find{|e| e[0] == “tag”} # =\> [“T%61G”, “lololo”]

Regards,  
Sean
