Tempura : references.ja.rd

# Tempura - リファレンスマニュアル

## テンプレートの書式

Tempuraのテンプレートは、REXMLでパース可能なXML形式のテキストとして表 現します。テンプレートは、`REXML::Document.new`に第一引数としてそ のまま渡されます。いくつかのXML属性とその値がTempuraの処理に利用されま す。

### XML属性

- _nil_ : XML要素を削除
- _child_ : XML要素の内容を属性値の評価結果で置換
- _self_ : XML要素自体を属性値の評価結果で置換
- _child_xml_ : XML要素の内容を属性値の評価結果をREXMLパースしたもので置換
- _self_xml_ : XML要素自体を属性値の評価結果をREXMLパースしたもので置換
- _attr_* : (接頭辞) XML属性とその値を置換
- _block_ : XML要素をブロックが呼ばれた回数分複製
- _event_ : aおよびform要素を「ユーザによるイベント」として変更
- _action_ : aおよびform要素において、_event_の送信先を変更
- _if_ : 属性値の評価結果が偽ならXML要素自体を削除 (暫定的に実装)
- _unless_ : 属性値の評価結果が真ならXML要素自体を削除 (暫定的に実装)

以上のXML属性がTempuraによる展開の結果に影響を与えます。これらのXML属 性自身は、Tempuraによる展開の出力結果からは削除されます。

以降、各XML属性の仕様を説明します。

_nil_

  この属性を持つXML要素をまるごと削除します。XMLの仕様上、属性値を省略 することはできませんが、値は無視されます。 XHTMLをプレビューするとき などに、ダミーのXML要素を置くのに使うことができます。

  例 (展開前):

      <ul>
        <li>天丼</li>
        <li>天ざる</li>
        <li _nil_="">(すきやき)</li>
      </ul>

  例 (展開後):

      <ul>
        <li>天丼</li>
        <li>天ざる</li>
      </ul>

_child_

  この属性を持つXML要素の内容を、属性値を評価した結果で置き換えます。 属性値は、Rubyスクリプトとして実行時に指定された環境(binding)で評価 されます。ただし例外として、_block_属性の影響下にあるときには、 ブロックの環境で評価されます。

  _self_がXML要素自体をまるごと置き換えるのに対して、_child_では、 XML要素の内容を置き換えます。

  評価の結果が:

  - nilだった場合、このXML要素自体を削除します。
  - falseだった場合、何もしません。
  - REXML::Childのインスタンスだった場合、そのまま置き換えます。
  - その他のオブジェクトの場合、to_sで文字列にしてテキスト要素として置 き換えます。

  例 (展開前):

      <p _child_="Time.now">current time</p>

  例 (展開後):

      <p>Wed Sep 17 17:47:35 JST 2003</p>

_self_

  この属性を持つXML要素自体を、属性値を評価した結果で置き換えます。属 性値は、実行時に指定された環境(binding)でRubyスクリプトとして評価さ れます。ただし例外として、_block_属性の影響下にあるときには、 ブロックの環境で評価されます。

  _child_がXML要素自体ではなく内容を変更するのに対して、_self_で は、XML要素自体を置き換えます。

  評価の結果が:

  - nilだった場合、このXML要素自体を削除します。
  - falseだった場合、何もしません。
  - REXML::Childのインスタンスだった場合、そのまま置き換えます。
  - その他のオブジェクトの場合、to_sで文字列にしてテキスト要素として置 き換えます。

  例 (展開前):

      <p _self_="Time.now">current time</p>

  例 (展開後):

      Wed Sep 17 17:47:35 JST 2003

_child_xml_, _self_xml_

  それぞれ_child_、_self_と基本的には同じです。しかし、評価の結果が、 nil・false・REXML::Childのインスタンスのいずれでもないとき(その他の オブジェクトの場合)の振舞いが異なります。

  - nilだった場合、このXML要素自体を削除します。
  - falseだった場合、何もしません。
  - REXML::Childのインスタンスだった場合、そのまま置き換えられます。

  ここまでは、それぞれ_child_、_self_と同じですが

  - その他のオブジェクトの場合、to_sで文字列にした評価結果をREXMLでパー スした結果で置き換えます。

  となります。

  _child_と_self_では、文字列に変換した評価結果がXML形式であろうがなか ろうが、まるごとテキスト要素として扱われます。

  それに対して、_ child_xml_と_self_xml_では、文字列に変換した評価結果 をREXMLで一度パースします。したがってXML形式の文字列はREXML::Childの インスタンスとして扱われることになります。

  この_xml_という接尾辞がつくXML属性は、評価結果がXML形式の文字列を返 すことが想定される場合、それを文字列でなくXML部品として扱いたいとき に使います。具体的には、XMLで書かれたTempura::Divテンプレートの中に、 Div標準のErbで書かれたDiv::Divテンプレートを埋め込むときなどに使います。

  以下に、`@erbdiv.to_div(context)`を評価した結果が `"<div>hello</div>"` という文字列を返す場合の、_xml_接尾辞の有無 による結果の違いを例示します。

  - 例 - _xml_有 (展開前):

        <body _child_xml_="@erbdiv.to_div(context)">hoge</body>
        <body _self_xml_="@erbdiv.to_div(context)">hoge</body>

  - 例 - _xml_有 (展開後):

        <body><div>hello</div></body>
        <div>hello</div>

  - 例 - _xml_無 (展開前):

        <body _child_="@erbdiv.to_div(context)">hoge</body>
        <body _self_="@erbdiv.to_div(context)">hoge</body>

  - 例 - _xml_無 (展開後):

        <body>&lt;div&gt;hello&lt;/div&gt;</body>
        &lt;div&gt;hello&lt;/div&gt;

  この結果から、ErbによるDiv::Divを埋め込む場合には、 _child_xml_や_self_xml_の方が役に立つだろうことが推測できるでしょうか。

_attr_* (名前が_attr_で始まるXML属性)

  この属性を持つXML要素の指定された属性を、属性値を評価した結果を文字 列化したもので、置き換えます。_attr_*属性名の_attr_ を取り除いたもの が変更される属性(ターゲット属性)の名前になります。

  属性値は、実行時に指定された環境(binding)でRubyスクリプトとして評価 されます。ただし例外として、_block_属性の影響下にあるときには、 ブロックの環境で評価されます。評価の結果により、以下のようにターゲッ ト属性を変更します。

  - nilだった場合、ターゲット属性自体を削除
  - falseだった場合、何もしません
  - それ以外の場合、ターゲット属性の値を評価結果を文字列にしたもので置換

  例 (展開前):

      <p _attr_time="Time.now">hello world</p>

      <option _attr_selected="nil" selected="true"/>
      <option _attr_selected="false" selected="true"/>
      <option _attr_selected="%(false)" selected=="true"/>
      <option _attr_selected="true"/>
      <option _attr_selected="%(true)"/>

  例 (展開後):

      <p time="Wed Sep 17 17:47:35 JST 2003">hello world</p>

      <option/>
      <option selected="true"/>
      <option selected=="false"/>
      <option selected="true"/>
      <option selected="true"/>

_block_

  この属性を持つXML要素を、特定書式の属性値の内容にしたがって、複製し ます。属性値はつぎの書式で記述します。

      _block_属性値 := Rubyスクリプト片 '//' ブロックメソッド名 '//' ブロック引数リスト

  Rubyスクリプト片の評価結果に対して、ブロックメソッドが呼ばれます。ブ ロックが呼ばれた回数だけXML要素が複製されます。複製されたXML要素は、 ブロックの環境(binding)でTempura展開されます。

  例1 (展開前):

      <li _block_="1..3//each//i" _child_="i">(will be replaced)</li>

  例1 (展開後):

      <li>1</li><li>2</li><li>3</li>

  例2 (展開前):

      <tr _block_="{:aaa=>111,:bbb=>222,:ccc=>333}//each//key,val">
        <td class="key" _child_="key">(key)</td>
        <td class="val" _child_="val">(val)</td>
      </tr>

  例1 (展開後):

      <tr>
        <td class="key">aaa</td>
        <td class="val">111</td>
      </tr><tr>
        <td class="key">bbb</td>
        <td class="val">222</td>
      </tr><tr>
        <td class="key">ccc</td>
        <td class="val">333</td>
      </tr>

_event_

  この属性を持つXML要素の名前が"a"または"form"の場合に、その要素をユー ザのWEBアプリケーションに対する操作として扱い、特定書式の属性値の内 容にしたがって変更します。その他の要素の場合には何もしません。属性値 はつぎの書式で指定します。

      _event_属性値 := イベント名 [ パラメータ ]*
      パラメータ    := '//' キー '==>' 値

  例1 - form要素 (展開前):

      <form method="POST" _event_="add">
        name: <input type="text" name="name"/>
        age : <input type="text" name="age"/>
        <input type="submit" value="add"/>
      </form>

  例1 -form要素 (展開後):

      <form method="POST" action="myapp.cgi"><input type="hidden" name="event" value="hello"/>
        item : <input type="text" name="item"/>
        price: <input type="text" name="price"/>
        <input type="submit" value="add"/>
      </form>

  例2 - a要素 (展開前):

      <a href="dummy" _event_="add//item==>%(tenzaru)//price==>9//time==>Time.now.to_i">add tenzaru</a>

  例2 -a要素 (展開後):

      <a href="myapp.cgi?event=add;item=tenzaru;price=9;time=1064208436">add tenzaru</a>

  例3 - Div (展開前):

      <form method="POST" _event_="add">
        name: <input type="text" name="name"/>
        age : <input type="text" name="age"/>
        <input type="submit" value="add"/>
      </form>

  例3 -Div (展開後):

      <form method="POST" action="/div">
          <input name='div_id' type='hidden' value='123456789'/>
          <input name='div_cmd' type='hidden' value='add'/>
        item : <input type="text" name="item"/>
        price: <input type="text" name="price"/>
        <input type="submit" value="add"/>
      </form>

_action_

  この属性は、_event_属性と組み合わせて使うためのもので、aおよび form要素のイベントの送信先を変更します。

  この属性を持つXML要素が、"a"または"form"という名前で、かつ _event_属性を持っている場合に、_event_によって展開される action名が、この属性の値に置き換えられます。テンプレート展開後のform 要素のaction属性、もしくはa要素のhref属性の値に影響します。この属性 による置き換えは、最優先されます。

  例1 - form要素 (展開前):

      <form method="POST" _event_="hello" action="dummy.cgi" _action_="alt.cgi">
      </form>

  例1 -form要素 (展開後):

      <form method="POST" action="alt.cgi"><input type="hidden" name="event" value="hello"/>
      </form>

  例2 - a要素 (展開前):

      <a href="dummy.cgi" _action_="alt.cgi" _event_="hello">hello</a>

  例2 -a要素 (展開後):

      <a href="alt.cgi?event=hello">hello</a>

## 文字コード変換器

Tempuraテンプレートにはそれぞれ文字コード変換器を指定することができま す。Tempura内部では、文字コードをUTF-8で扱います。UTF-8以外の文字コー ドで記述されたテンプレートを使うためには、その文字コードとUTF-8を相互 に変換するための文字コード変換器を指定する必要があります。

文字コード変換器は、つぎの２つのインスタンスメソッドを備えた任意のオブ ジェクトです。

`文字コード変換器#to_u8(str)`

  文字列をUTF-8文字列に変換して返す。

`文字コード変換器#from_u8(str)`

  UTF-8文字列を8文字列に変換して返す。

あらかじめ以下の文字コード変換器が定義されています。

Tempura::CharConvDefault

  何もしない変換器。デフォルト。

Tempura::CharConvEUC

  EUC-JPのための変換器。

Tempura::CharConvSJIS

  ShiftJISのための変換器。

## クラス

### Tempura::Templateクラス

複数のTempuraテンプレートと１つのTempura展開器を包むオブジェクトを定義 するクラスです。選択されたテンプレートを引数として与えられたデータで展 開する機能を持っています。Tempuraを典型的なテンプレートライブラリとし て使う場合、通常はこのクラスのインスタンスを生成して使います。

このクラスのインスタンスは、デフォルトテンプレートを含む複数のテンプレー トを持つことができます。各テンプレートは特定のキーオブジェクトと関連づ けられます。展開時に、与えられたキーに関連づけられたテンプレートが見つ からない場合は、デフォルトテンプレートが使用されます。

各テンプレートはそれぞれ関連する文字コード変換器を持つことができます。

#### ロード:

`require 'tempura/template'`

#### クラスメソッド:

`Tempura::Template.new([path, charconv, safe_level])`

  Tempura::Templateオブジェクトを生成します。pathには、デフォ ルトテンプレートを記述したファイルへのパスを指定します。 charconvには文字コード変換器を指定します。 safe_levelはテンプレートを展開するときの$SAFEの値を指定しま す。

`Tempura::Template.new_with_string(str[, charconv, safe_level])`

  Tempura::Templateオブジェクトを生成します。strには、デフォル トテンプレートを記述した文字列を指定します。charconvには 文字コード変換器を指定します。safe_levelはテンプレート を展開するときの$SAFEの値を指定します。

#### メソッド:

`Tempura::Template#default_action`

  _event_属性を展開するときにaction属性の値とする文字列を返します。 デフォルトは空文字列""です。この値は、テンプレート展開後のform要素 のaction属性、もしくはa要素のhref属性の値に、影響します。

`Tempura::Template#default_action=(str)`

  _event_属性を展開するときに、action属性の値とする文字列を設定しま す。この値は、テンプレート展開後のform要素のaction属性、もしくはa 要素のhref属性の値に、影響します。

  `default_action = "myapp.cgi"` のとき

      <form  method="POST" _event_="hello">
      ...
      </form>
      <a href="dummy" _event_="hello">hello</a>

  の展開結果は

      <form method="POST" action="myapp.cgi"><input type="hidden" name="event" value="hello"/>
      ...
      </form>
      <a href="myapp.cgi?event=hello">hello</a>

  となります。

`Tempura::Template#default_event_key`

  _event_属性を展開するときに、eventを表すキー文字列として展開する文 字列を返します。デフォルトは"event"です。

`Tempura::Template#default_event_key=(val)`

  _event_属性を展開するときに、eventを表すキー文字列として展開する文 字列を設定します。

  `default_event_key = "mycmd"` のとき

      <form  method="POST" _event_="hello">
      ...
      </form>
      <a href="dummy" _event_="hello">hello</a>

  の展開結果は

      <form method="POST" action=""><input type="hidden" name="mycmd" value="hello"/>
      ...
      </form>
      <a href="?mycmd=hello">hello</a>

  となります。

`Tempura::Template#set(path[, key, charconv])`

  pathで指定されたファイルの内容を、keyと関連づけられた テンプレートとして設定します。keyが省略された場合はデフォル トテンプレートとなります。charconvには文字コード変換器 を指定します。

`Tempura::Template#set_with_string(str[, key, charconv])`

  strで指定された文字列を、keyと関連づけられたテンプレー トとして設定します。keyが省略された場合はデフォルトテンプレー トとなります。charconvには文字コード変換器を指定します。

`Tempura::Template#expand(model[, key])`

  modelと関連付けられた環境(binding)で、keyと関連付けら れたテンプレートを展開し、結果を文字列として返します。keyが 省略された場合はデフォルトテンプレートを展開します。

  modelが

  Bindingインスタンスの場合

    テンプレートはその環境(binding)で評価されます

  その他のインスタンスの場合

    テンプレートはインスタンスの環境(binding)で評価されます

`Tempura::Template#expand_to_document(model[, key])`

  modelと関連付けられた環境(binding)で、keyと関連付けら れたテンプレートを展開し、結果をREXML::Documentインスタンスとして 返します。keyが省略された場合はデフォルトテンプレートを展開 します。

### Tempura::Divクラス

テンプレートにTempuraテンプレートを使うDiv::Divの派生クラスです。Divに ついては Divのウェブサイト などを参照してください。

#### スーパークラス:

Div::Div

#### ロード:

`require 'tempura/div'`

#### クラスメソッド:

`Tempura::Div.new(session)`

  Tempura::Divオブジェクトを生成します。

`Tempura::Div.set_template(path[, key, charconv])`

  pathで指定されたファイルの内容を、keyと関連づけられた テンプレートとして設定します。keyが省略された場合はデフォル トテンプレートとなります。charconvには文字コード変換器 を指定します。

`Tempura::Div.set_safe_level(safe_level)`

  テンプレートを展開するときの$SAFEの値を指定します。

`Tempura::Div.reload_template`

  テンプレートをファイルから再読み込みします。

#### メソッド:

`Tempura::Div#select_template(key)`

  与えられたキーと関連付けられたテンプレートをデフォルトテンプレート にします。

`Tempura::Div#to_html_document([context, key])`

  レシーバインスタンスの環境(binding)で、keyと関連付けられたテ ンプレートを展開し、結果をREXML::Documentインスタンスとして返しま す。keyが省略された場合はデフォルトテンプレートを展開します。 Erbで書かれたDivテンプレートの中から呼ぶ場合は、このメソッドでなく、 文字列を返すバージョンのTempura::Div#to_htmlを呼ぶべきです。

`Tempura::Div#to_html([context, key])`

  レシーバインスタンスの環境(binding)で、keyと関連付けられたテ ンプレートを展開し、結果を文字列として返します。keyが省略さ れた場合はデフォルトテンプレートを展開します。Tempuraテンプレート で書かれたDivテンプレートの中から呼ぶ場合は、このメソッドでなく、 REXML::Documentインスタンスを返すバージョンの Tempura::Div#to_html_document を呼ぶ方が効率的です。

`Tempura::Div#to_div_document([context, key])`
`Tempura::Div#to_div([context, key])`

### Tempura::Expanderクラス

Tempuraテンプレート展開器を定義するクラスです。このクラスが、Tempuraの 核心部といえます。とくにカスタマイズなどをする必要がなければ、通常はこ のクラスを直接扱う必要はありません。

#### ロード:

`require 'tempura/expander'`

#### クラスメソッド:

`Tempura::Expander.pre_expand(rexml_element[, bang_p])`
`Tempura::Expander.new([safe_level])`

#### メソッド:

`Tempura::Expander#safe_level`
`Tempura::Expander#pre_expand(rexml_element[, bang_p])`
`Tempura::Expander#expand(context, rexml_element, charconv[, bang_p])`
`Tempura::Expander#expand_to_string(context, rexml_element, charconv[, bang_p])`
`Tempura::Expander#default_action`
`Tempura::Expander#default_action=(action)`
`Tempura::Expander#default_event_key`
`Tempura::Expander#default_event_key=(event_key)`
`Tempura::Expander#param_filter(&proc)`
`Tempura::Expander#action_filter(&proc)`

### Tempura::SourceContainerクラス

Tempuraテンプレートソース(Tempura::Sourceインスタンス)のコンテナを定義 するクラスです。各テンプレートはキーオブジェクトと関連付けられて管理さ れます。通常はこのクラスを直接扱う必要はありません。

#### ロード:

`require 'tempura/source_container'`

#### クラスメソッド:

`Tempura::SourceContainer.new`

#### メソッド:

`Tempura::SourceContainer#[key]`
`Tempura::SourceContainer#[key] = val`
`Tempura::SourceContainer#default`
`Tempura::SourceContainer#default=(val)`
`Tempura::SourceContainer#set(key, path[, charconv])`
`Tempura::SourceContainer#set_as_string(key, string[, charconv])`
`Tempura::SourceContainer#reload`

### Tempura::Sourceクラス

REXML::Documentインスタンスと関連する文字コード変換器を包むオブジェク トを表現するクラスです。通常はこのクラスを直接扱う必要はありません。

#### ロード:

`require 'tempura/source'`

#### クラスメソッド:

`Tempura::Source.new_with_string(str[, charconv])`
`Tempura::Source.new(path[, charconv])`

#### メソッド:

`Tempura::Source#path`
`Tempura::Source#charconv`
`Tempura::Source#name`
`Tempura::Source#name=(val)`
`Tempura::Source#reload`
`Tempura::Source#fetch_document`