"Austin Ziegler" <halostatue@gmail.com> schrieb im Newsbeitrag
news:9e7db91104072904276f6d064e@mail.gmail.com...
> 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
> '<html> '+yield'</html> '
> end
> end
Briefly, this would better be:
class HtmlTag < Tag
def to_s
"<html>#{yield}</html>"
end
end
However, most #to_s implementations aren't going to yield anything,
And that's why one shouldn't override to_s with a version expecting a
block.
and I don't think that blocks bind to implicit method calls, if the
implicit method call is used in any case.
It can't since the invocation of #to_s is *in* Kernel#puts, i.e. that
method looks something like
def puts(*args)
args.each do |o|
# here's the #to_s invocation - no chance
# to hand over the block:
str = o.to_s
send_to_output str
end
end
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).
CGI#html is a good example - and btw. maybe that's all you really need.
No need to invent the wheel twice.
If you want to do it manually, best is probably:
def html(attrs = {})
str = "<html"
attrs.each {|at, val| str << " " << at << "=\"" << val << "\""}
str << ">"
str << yield
str << "</html>"
end
But, as said, the functionality is already there plus CGI takes care of
different HTML versions.
Kind regards
robert
···
On Thu, 29 Jul 2004 19:31:48 +0900, Daniel Völkerts > <dvoelkerts@web.de> wrote: