XHTML generátor skrze method_missing v Ruby

2. 6. 2007 21:19 botanicus

Dnes jsem si po nějaké době zase hrál s Ruby a přišel jsem na docela vtipné využití. Pro nápad jsem nemusel chodit nikterak daleko, stačilo jej trochu poupravit. Jedná se o využití metody method_missing na generaci XML. Pak již není nic jednoduššího než předhodit jí neexistující metody a generovat X(HT)ML. Po chvilce hraní jsem došel k tomuto:

  def method_missing(tag,*args,&block)
$indent = 0 if not defined?($indent)
if block_given?
if args.empty?
puts("#{" " * $indent}<#{tag}>")
else
puts("#{" " * $indent}<#{tag} #{args.join(" ")}>")
end
$indent += 2
output = block.call
puts("#{" " * $indent} #{output}") if output.kind_of?(String)
$indent -= 2 if $indent > 0
puts("#{" " * $indent}</#{tag}>")
else
if args.empty?
puts("#{" " * $indent}<#{tag} />")
else
puts("#{" " * $indent}<#{tag} #{args.join(" ")} />")
end
end
end

Tak například tento RubyML (nebo jak to nazvat)

  html('xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"') do
head do
meta('http-equiv="Content-Type" content="text/html; charset=utf-8"')
title { "Ruby XHTML generator" }
end
body do
h1('class=xyz') { "Ruby XHTML generator" }
strong('class="bold"') { "Text tucne" }
em('class="xzv"') {
"Normalni text kurzivou...."
}
br
end
end


… generuje toto:

  <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>
Ruby XHTML generator
</title>
</head>
<body>
<h1 class=xyz>
Ruby XHTML generator
</h1>
<strong class="bold">
Text tucne
</strong>
<em class="xzv">
Normalni text kurzivou....
</em>
<br />
</body>
</html>

Lze si tím těch pár znaků ušetřit. Kdyby se ta myšlenka trochu rozvinula, dal by se na jejím základě udělat lehký XML generátor. Minimálně pro rychlé bastlení by to svůj význam určitě mělo (na větší věci samozřejmě používám Rails, ale když chce člověk třeba jen napsat článek, zápisek do blogu nebo tak něco, tak proč ne). Samozřejmě by se nejdřív musel oddělit namespace a tedy method_missing volat z konkrétní třídy, jak to ostatně v onom odkazovaném článku je. Pak by už nebyl problém používat cykly, proměnné atp. jako v normálním programování, akorát by to jednoduše přímo produkovalo XML.

PS: Nevyčítejte mi prosím, že je to bastl a že tomu chybí tamto a támhleto, prostě jsem si jenom trochu hrál ;)

Sdílet