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

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.
[email protected]

Hi,

2008/5/23 Iñaki Baz C. [email protected]:

   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.

2008/5/23, Heesob P. [email protected]:

           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.

Hi,

2008/5/23 Iñaki Baz C. [email protected]:

                   __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.

2008/5/23, Heesob P. [email protected]:

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.

On Fri, May 23, 2008 at 11:21 AM, Iñaki Baz C. [email protected] wrote:

                   __getobj__[k]
   from (irb):6:in `find'


Iñaki Baz C.
[email protected]

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