From 48653d5ef0ed47469d64170d70c8c2a9f21f159e Mon Sep 17 00:00:00 2001 From: matz Date: Mon, 5 Sep 2005 08:29:52 +0000 Subject: * lib/ostruct.rb: a patch from Florian Gross merged to allow recursive inspect (and to_s) for OpenStruct. [ruby-core:05532] * lib/observer.rb: a patch from nornagon merged to allow arbitrary names for update methods. [ruby-core:05416] * eval.c (rb_f_fcall): new method to avoid inefficiency of obj.instance_eval{send(...)} tricks. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9081 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- lib/ostruct.rb | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) (limited to 'lib/ostruct.rb') diff --git a/lib/ostruct.rb b/lib/ostruct.rb index b30ae640c5..6af5bbdac0 100644 --- a/lib/ostruct.rb +++ b/lib/ostruct.rb @@ -47,7 +47,7 @@ class OpenStruct @table = {} if hash for k,v in hash - @table[k.to_sym] = v + @table[k.to_sym] = v new_ostruct_member(k) end end @@ -68,11 +68,11 @@ class OpenStruct end def new_ostruct_member(name) + name = name.to_sym unless self.respond_to?(name) - self.instance_eval %{ - def #{name}; @table[:#{name}]; end - def #{name}=(x); @table[:#{name}] = x; end - } + meta = class << self; self; end + meta.send(:define_method, name) { @table[name] } + meta.send(:define_method, :"#{name}=") { |x| @table[name] = x } end end @@ -81,14 +81,14 @@ class OpenStruct len = args.length if mname =~ /=$/ if len != 1 - raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1) + raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1) end if self.frozen? - raise TypeError, "can't modify frozen #{self.class}", caller(1) + raise TypeError, "can't modify frozen #{self.class}", caller(1) end mname.chop! - @table[mname.intern] = args[0] self.new_ostruct_member(mname) + @table[mname.intern] = args[0] elsif len == 0 @table[mid] else @@ -103,16 +103,35 @@ class OpenStruct @table.delete name.to_sym end + InspectKey = :__inspect_key__ # :nodoc: + # # Returns a string containing a detailed summary of the keys and values. # def inspect - str = "<#{self.class}" - for k,v in @table - str << " #{k}=#{v.inspect}" + str = "#<#{self.class}" + + Thread.current[InspectKey] ||= [] + if Thread.current[InspectKey].include?(self) then + str << " ..." + else + first = true + for k,v in @table + str << "," unless first + first = false + + Thread.current[InspectKey] << v + begin + str << " #{k}=#{v.inspect}" + ensure + Thread.current[InspectKey].pop + end + end end + str << ">" end + alias :to_s :inspect attr_reader :table # :nodoc: protected :table -- cgit v1.2.3