From: nobu.nakada@... Date: 2002-11-15T08:58:13+09:00 Subject: [ruby-dev:18794] Re: observer.rb, ostruct.rb: NameError -> NoMethodError なかだです。 At Fri, 15 Nov 2002 00:37:00 +0900, NAKAMURA, Hiroshi wrote: > ostruct.rbのほうは、キーがsymbolに変わったときの > 修正漏れがあるようです(パッチの一番最後のブロック)。 initializeにhashを渡したときの処理がおかしいような気がします。 値ではなくキーをto_symしないといけないのでは。 あとdefine_methodで高速化(?)を図るのと、inspectで+=を繰り返すの ではなく<<を使うというのも。 Index: ostruct.rb =================================================================== RCS file: /cvs/ruby/src/ruby/lib/ostruct.rb,v retrieving revision 1.4 diff -u -2 -p -r1.4 ostruct.rb --- ostruct.rb 14 Nov 2002 22:46:00 -0000 1.4 +++ ostruct.rb 14 Nov 2002 23:57:17 -0000 @@ -14,5 +14,5 @@ class OpenStruct if hash for k,v in hash - @table[k] = v.to_sym + @table[k.to_sym] = v end end @@ -22,18 +22,30 @@ class OpenStruct mname = mid.id2name len = args.length - if mname =~ /=$/ - if len != 1 + if mname.sub!(/=\z/, '') + unless len == 1 raise ArgumentError, "wrong # of arguments (#{len} for 1)", caller(1) end - mname.chop! - @table[mname.intern] = args[0] - elsif args.length == 0 - @table[mid] + setter = mid + getter = mid = mname.intern + ret = @table[mid] = args[0] + elsif len == 0 + getter = mid + setter = "#{mid}=".intern + ret = @table[mid] else raise NoMethodError, "undefined method `#{mname}'", caller(1) end + class << self; self; end.class_eval do + define_method(getter, proc {|| @table[mid]}) + define_method(setter, proc {|v,| @table[mid] = v}) + end + ret end def delete_field(name) + class << self + remove_method(name) + remove_method("#{name}=") + end @table.delete name.to_sym end @@ -42,11 +54,7 @@ class OpenStruct str = "<#{self.class}" for k,v in @table - str += " " - str += k.to_s - str += "=" - str += v.inspect + str << " #{k}=#{v.inspect}" end - str += ">" - str + str << ">" end end -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦