From: Heesob Park Date: 2008-05-23T18:16:13+09:00 Subject: Re: Help extending Hash to allow hexadecimal encoded keys (problem with "Delegator") Hi, 2008/5/23 IƱaki Baz Castillo : > 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. > > 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 Heesob