On Wed, May 22, 2002 at 06:09:37AM +0900, Ian Macdonald wrote:
> On Tue 21 May 2002 at 01:00:22 +0900, Wakou Aoyama wrote:
> 
> I saw this as a great opportunity to try out Object#method_missing.
> 
> You can get a simple, yet quite effective method for handling any kind
> of tag, by using the following interceptor method:
> 
> module HTML
>   def method_missing(methId, data, attrs = {})
>     tag = methId.id2name
>     tag.upcase!
>     attr_str = ''
>     attrs.each do |key, value|
>       attr_str << sprintf(' %s="%s"', key.upcase, value)
>     end
>     sprintf("<%s%s>%s</%s>", tag, attr_str, data, tag)
>   end
> end
> 
> 
> You then call it like this:
> 
> require 'html'
> include HTML
> 
> puts a('Google', 'href' => 'http://www.google.com/')
> puts ul(li('item1') + li('item2') + li('item3'))
> 
> 
> The output looks like this:
> 
> Google
> <UL><LI>item1</LI><LI>item2</LI><LI>item3</LI></UL>
>   

Very nice Ian. I played a little golf with your
code and came up with the following:

module HTML
  def method_missing(methId, data, attrs={})
    tag = methId.id2name
    attr = attrs.collect { |k,v| " #{k}=\"#{v}\"" }.join
    "<#{tag}#{attr}>#{data}</#{tag}>"
  end
end

It does the same thing, but is a little more compact.
Then, I took an old html class I had written and added
method missing.

module HTML2
  def method_missing(methId, attrs={}, &block)
    tag = methId.id2name
    attr = attrs.collect { |k,v| " #{k}=\"#{v}\"" }.join
    "<#{tag}#{attr}>" << yield << "</#{tag}>"
  end
end

The modules can be used as:

class A; include HTML; end
a=A.new
puts a.a("Link", {'href'=>'http://mylink'}) 
puts a.h1("Title") 

# Output
 Link
 <h1>Title</h1>

--
class A2; include HTML2; end
a=A2.new
puts a.a({'href'=>'http://mylink'}) { a.h1 { "Title" } }

# Output
 <a href="http://mylink"><h1>Title</h1></a>


I like what you did, but I think I like the html2 better
since it is seems easier to encapsulate with blocks (at least to me).
Then, I made a slight modification to handle single instance
entities:

module HTML2
  def method_missing(methId, attrs={}, &block)
    tag = methId.id2name
    attr = attrs.collect { |k,v| " #{k}=\"#{v}\"" }.join
    if block_given?
      "<#{tag}#{attr}>" << yield << "</#{tag}>"
    else
      "<#{tag}#{attr}>"
    end
  end
end

class A2; include HTML2; end
a=A2.new
puts a.a({'href'=>'http://mylink'}) { a.h1 { "Title" } }, a.br

#Output
<a href="http://mylink"><h1>Title</h1></a>
<br>

Thanks for the inspiration. However, as you said, I'm sure
someone has done this long ago. But it definitely makes
for a very short html utility, even if it doesn't check
for validity.

-- 
Jim Freeze
If only I had something clever to say for my comment...