Gestaltさんの使い方

Ramazeさんには Ramaze::Gestalt というライブラリが存在しております。え、Gestalt!なんか名前が怖いよ!と思われるかも知れませんが、これはとっても素敵な感じで簡単にHTMLを構築することが出来るものです。Markaby に相当するもの、と考えておけば良いのではないでしょうか。とっても簡単なので使い方など説明不要という感じさえしますが、いかんせん地味な存在ですので(名前のせい?)、皆さんに興味を持ってもらえるように紹介しておきたいと思います。

使い方

まず気をつけておかなければならない事ですが、Ramaze::Gestaltを使う時には明示的にライブラリをロードする必要があります。つまり require "ramaze" だけでは読み込んでくれないんですよね。

require "ramaze/gestalt"

Ramaze::Gestalt.build do
  html do
    body "..."
  end
end
# => <html><body>...</body></html>

というわけで、require "ramaze/gestalt" を忘れずに。

さて、上の例で既に大概の事は分かるかと思いますが、要素を作るには、Ramaze::Gestalt.build のブロック内で適当にそれっぽく html とか body とかの要素名をメソッドとして呼び出してやるだけです。この時ブロックを渡してやればそれが要素の子要素になります。また引数に文字列を渡すこともできます。実装的には単純に method_missing を使っていますので、HTMLの要素だろうがなんだろうがレンダリングできてしまいます。

require "ramaze/gestalt"

Ramaze::Gestalt.build { parent{ child } }
# => <parent><child /></parent>

Ramaze::Gestalt.build { parent "child" }
# => <parent>child</parent>

Ramaze::Gestalt.build { parent {"child"} }
# => <parent>child</parent>

Ramaze::Gestalt.build { xxx }
# => <xxx />

ただし、現時点ではXML名前空間などは考慮されていないため、接頭辞付きの要素(rdf:RDFみたいなの)を作れません(ホントは_gestalt_call_tagを直接呼び出せば出来ますが、これをやるくらいならGestalt使わないと思います)。あと、小文字は問題ないけど、一文字目が大文字の名前を持つ要素が作れません(こっちは"()"つけて呼び出せばいいだけだから、問題でもない?)。多分直した方が良いと思うのですが、どうしたものでしょう。

次に属性値の設定方法ですが、これは素直にHashで渡せば良いだけです。

require "ramaze/gestalt"

Ramaze::Gestalt.build { elt :id => :test, :hoge => :hoga }
# => <elt hoge="hoga" id="test" />

# 接頭辞付きの属性も指定できます
Ramaze::Gestalt.build { elt "prefix:local" => :value }
=> <elt prefix:local="value" />

Ramaze::Gestalt.build { parent(:style => "text-decoration: none;"){child} }
# => <parent style="text-decoration: none;"><child /></parent>

# ただし、文字列と属性値の両方を指定することは出来ないので注意
# これは出来た方が良いと思うんだけど
Ramaze::Gestalt.build { parent "child", :style => "text-decoration: none;" }
=> "<parent>childstyletext-decoration: none;</parent>"

そんなわけで、とっても簡単ですね!

感想

ていうか、Markabyと思い切り被ってますよね。MarkabyはHTML/XHTML専用なので使い分けが出来ることは出来ますが、ほとんどの場合はHTML/XHTMLを構築するのに使われると思いますので、使い所に悩むかも知れません。しかも現状では、id や class の記法をサポートしていたりする心配りがある分、Markabyの方が優れているだろうと思います。というわけで、もう少しXMLにおける汎用的な側面を強化しないとダメなのかも。でも標準で付いてきますから、その点Ramazeがインストールされている環境では安心して使えるという利点はあると思います。皆さん使いましょう。そして改良しましょう。

追記:一文字目が大文字の要素について

考えてみたら、要素を作成する時にはほとんどの場合その子要素か属性かを指定するだろうから、実際には何も問題がないのだろう、と思いました。

require "ramaze/gestalt"

Ramaze::Gestalt.build { HTML{BODY{"..."}} }
# => <HTML><BODY>...</BODY></HTML>

Ramaze::Gestalt.build { META :hello => :world }
=> <META hello="world" />

# 子要素も属性もない時には仕方ないから()を付けて明示的にメソッドを呼び出して下さい
Ramaze::Gestalt.build { BR() }
=> <BR />

難しい事は考えずにこれで良いと思います!