HTML form management on Xslate
<追記>
@typesterさんの指摘を受けて再考中。確かに、気軽にrawを書くようになると、結局「うっかりraw」をする可能性が生じて安全性が下がります。テンプレートではrawを使うべきではない、ということを前提にドキュメントと記事を書き直しました。
参考:
@fujiwara:うっかりraw付ける付けないのミスというより、化ける!→rawつけると化けない!→じゃあとりあえずrawつけとけばイイよね! みたいな流れがありがち。
@tokuhirom:ていうか、T::MT の思想では、基本的に model とか controller 側で raw 属性つける、なんだよね。
追記>Xslate上でフォーム処理をしようとしたらいろいろハマったのでCookbook書きました。
http://search.cpan.org/dist/HTML-Shakan=HTML::Shakanなどのフォームビルダーは、アプリケーションコードで出力の際にmark_raw()でraw stringにしてください。
HTML::FillInFormを使う場合がちょっと厄介で、簡単な方法がなかったので*1新しい構文を加えることにしました(0.1038から)。blockに対してその場でフィルタをかますことができるようになります。
Cookbookからのコピペですがこんな感じです。
#!perl -w use strict; use Text::Xslate qw(mark_raw); use HTML::FillInForm; sub fillinform { my($q) = @_; return sub { my($html) = @_; return mark_raw(HTML::FillInForm->fill(\$html, $q)); }; } my $tx = Text::Xslate->new( function => { fillinform => \&fillinform, }, ); my %vars = ( q => { foo => "<filled value>" }, ); print $tx->render_string(<<'T', \%vars); FillInForm: : block form | fillinform($q) | raw -> { <form> <input type="text" name="foo" /> </form> : } T __END__
さらに、いちいちfillinform()
を書くのがかったるい!という方向けに、HTML::FillInForm::Liteにはエクスポート可能なfillinform()
関数を追加しました(1.09から)。fillinform($html, $data)
とすれば$htmlにfill()
した結果を返し、fillinform($data)
とすれば上記のようなcurry化したサブルーチンを返します。
つまり、Text::Xslate->new( module => ['HTML::FillInForm::Lite' => [qw(fillinform)]] )
とするだけでfillinform($q)
フィルタが使えるので便利です。ただしrawフィルタが必要なのは変わりません。安全第一。
<追記>
テンプレート側でrawをするべきではない、という原則に従うと、上記のインターフェイスをそのまま使うのは奨励できません。関数インターフェイスを使う場合でも、以下のように一段ラッパーを書いたほうが安全です。
use Text::Xslate qw(mark_raw); use HTML::FillInForm::Lite qw(fillinform); my $tx = Text::Xslate->new( function => sub { my($q) = @_; return sub { mark_raw(fillinform($_[0], $q)) }; }, ); # 後は同じ
追記>
*1:マクロを定義してそれを明示的に呼び出すしかありませんでした。