Modifierもどきを実装
DHHのアドバイスに従い、Smartyの修正子(Modifier)もどきを実装してみた。ついでに、動的要素を示す属性の既定値をidからamrita:srcに変更。
t = TemplateText.new %[<x amrita:src='time|DateFormat["%Y-%m-%d %H:%M"]' />] t.expand(out="", :time=>Time.local(2006,6,19,22,30)) assert_equal("<x>2006-06-19 22:30</x>", out)
DateFormat["%Y-%m-%d %H:%M"]というのがModifierの例。システムで単純なものをいくつか用意するが、実装は次のように単純なので、簡単に追加できる。
class DateFormat < Amrita2::Modifier::Base def initialize(format) @format = format end def do_filter_data(data) data.strftime(@format) end end
複数の修飾子を並べて、順に適用させることもできる。(UNIXのパイプのイメージ?)
t = TemplateText.new %[<x amrita:src='time | Default[Time.local(2006,6,19)] | DateFormat["%m-%d"]' />] time1 = Time.local(2006,6,17) time2 = Time.local(2006,6,18) t.expand(out="", :time=>[time1, time2 ,nil]) assert_equal("<x>06-17</x><x>06-18</x><x>06-19</x>", out)
Defaultは、値がnilの時に、ここで指定した値と入れかえるModifier。
この記述方式に、amrita:type という、出力形式を変更するオプションの指定も統合する予定。
tmpl = TemplateText.new "<a amrita:src='a2|Link'>Amrita2</a>" data = { :a2 => 'http://amrita2.rubyforge.org/', } tmpl.expand(out="", data) assert_equal("<a href='http://amrita2.rubyforge.org/'>Amrita2</a>", out)
これは、前の書き方で言うと
"<a amrita:src='a2' amrita:type='link'>Amrita2</a>"
に相当する。今の時点では、amrita:typeというオプションは廃止して、この方式で統一しようと思っている。これの実装は次のようになっていて、
class Link < Base def set_option(opt) super opt[:link_attr] = [:href, [/javascript:.*/]] end end
自作するにはopt[:link_attr]の意味等を理解する必要はあるが、これも一応拡張(外付け)可能になった。option[:link_attr]の指定で動き出す機能も(現在の実装の迷路の中をさまよう覚悟さえあれば)一応拡張可能。ただし、このレベルのプラグインのAPIはちょっとやそっとではドキュメント化できません。
ちなみに、[/javascript:.*/]は、禁止URLの指定で、ここに渡した正規表現にマッチする属性値は削除される。つまり、http://...やftp://のような普通のURLは許されるけど、javascript:で始まるURLが渡されると、この属性は空白になる。
この変更で、API(というかプログラマ向けのインターフェース)は、少しは整理されたように思う。後は、DHHが言うように、View内でプレゼンテーションオブジェクト(View用データ作成の処理=特定アクション専用のHelperメソッド)が書けるようにして、なるべく早く次期バージョンをリリースしたい。