From: Austin Ziegler Date: 2004-07-29T20:27:40+09:00 Subject: Re: to_s isn't automatically called On Thu, 29 Jul 2004 19:31:48 +0900, Daniel V�lkerts wrote: > perhaps it is a newbies fault, but I can't figure out where to > find my logical failure. > > I'd like to build up a Tree for a Document. The result should > contain a string represantion of this document (e.g. HTML file). > > I started writing ... > > class Tag > def to_s > yield > end > end > > Thats easy so I went on ... > > class HtmlTag < Tag > def to_s > ' '+yield' ' > end > end Briefly, this would better be: class HtmlTag < Tag def to_s "#{yield}" end end However, most #to_s implementations aren't going to yield anything, and I don't think that blocks bind to implicit method calls, if the implicit method call is used in any case. That's actually where the problem is: > That looks the way I want it to look like, but if I call the following > Html = HtmlTag.new > # Okay, not valid HTML. Just for testing. > puts Html {'Hello'} > The interpreter returned > tags.rb:27: undefined method `Html' for main:Object (NoMethodError) > > I understand this messages as the Mainobject doesn't have such method, > but why doesn't he send a message to Html called 'to_s'? Because Ruby is seeing your statement as: puts Html() { 'Hello' } You've forced a method context. #to_s is called when a string form of the object is required -- and in many cases, a block will *not* be provided. (When I did something similar in irb, I got: irb(main):009:0> b = A.new LocalJumpError: no block given from (irb):3:in `to_s' ... You would need to manually call #to_s. Better would be to redesign your objects so that you're really calling a method (like CGI#html). class Tag def fill @string = yield end def to_s "#{@string} end end aa = Tag.new aa.fill { "Hello" } puts aa -austin -- Austin Ziegler * halostatue@gmail.com * Alternate: austin@halostatue.ca