From: "Florian Groß" Date: 2005-08-07T18:29:50+09:00 Subject: [PATCH] ostruct.rb: recursive inspect, .send with exotic symbols, return value of assignment --------------010007010801030106000007 Content-Type: text/plain; charset=ISO-8859-15; format=flowed Content-Transfer-Encoding: 7bit Moin. I've attached a patch for ostruct.rb (against 1.8.2, but I don't think there was changes to it lately) which makes the following work: > irb(main):001:0> o = OpenStruct.new > => # > irb(main):002:0> o.o = o > => #> > irb(main):003:0> o.foo = "bar" > => "bar" > irb(main):004:0> o > => #> > irb(main):005:0> o.to_s > => "#>" > irb(main):006:0> o.send(:"->=", "foo") > => "foo" > irb(main):007:0> o > => #="foo", foo="bar", o=#> It's mostly just small changes, but I think the recursive inspect is actually important. Making the inspect result more consistent with Object#inspect is probably also a good idea. Regards, Florian Gross --------------010007010801030106000007 Content-Type: text/plain; name="ostruct.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="ostruct.patch" --- ostruct.rb.original 2005-08-07 10:43:53.257125000 +0200 +++ ostruct.rb 2005-08-07 11:18:15.944625000 +0200 @@ -68,11 +68,11 @@ 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 @@ -87,8 +87,8 @@ 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 @@ @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}" + 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 --------------010007010801030106000007--