Text::Xslate TTerse の深淵なる罠
2012-12-15
みなさんこんにちわ!みなさんはテンプレート使ってますね! Xslate つかってますね! TTerse 使ってますね!今回はうっかりハマってしまう罠を教えます!
SET で作った変数はブロックスコープである
ブロックスコープなんだけど SET したスコープの中にあるブロックはスコープの対象外なので以下のテストは動かなかったりするんだ。
my $tx = Text::Xslate->new({
syntax => 'TTerse'
});
my $ret = $tx->render_string(<<TMPL,);
[% SET chin = 'kiru' -%]
[% MACRO xaicron BLOCK -%]
[% chin = 'kiranai' -%]
[% chin -%]
[% END -%]
[% xaicron() -%]
[% chin -%]
TMPL
is $ret, "kiranaikiranai"; # kiranaikiru が帰って来て失敗する
実は SET は飾り
変数の定義しなくても最初に出て来た時に SET したのと同等っぽいね。だから上のコードの xaicron マクロの中の最初の chin ってのは SET したのと同等ってわけさ。
深遠な理由で例外がある
色々あって次のようなケースはブロックスコープになってないんだけど、これ直しちゃうと影響範囲でかすぎるからきっとこのままっぽいね。
my $tx = Text::Xslate->new({
syntax => 'TTerse'
});
my $ret = $tx->render_string(<<TMPL,);
[% SET chin = 'kiru' -%]
[% IF 1 -%]
[% SET chin = 'kiranai' -%]
[% chin -%]
[% END -%]
[% chin -%]
TMPL
is $ret, "kiranaikiru"; # kiranaikiranai が帰って来て失敗する
あと関係無いけどこれの ELSIF の中での chin の定義で Text::Xslate::Compiler: Cannot modify chin, which is not a lexical variable って言われるんだけど(1.6001現在)これはバグなんで gfx が直してくれるはず!
[% IF 1 -%]
[% SET chin = 'kiru' -%]
[% ELSIF 0 -%]
[% SET chin = 'kiranai' -%]
[% END -%]
SET つかったら負け
基本的にはテンプレートでは複雑な事したら負けだし SET とかで頑張ってロジック組んじゃうとか愚か者なんだって!
要はSETをエイリアス以外の用途で使うなってことです! / “Text::Xslate TTerse の深淵なる罠 - Perl Advent Calendar Japan 2012 Casual Track” htn.to/F4WZ3j
— Fuji, Goroさん (@__gfx__) 12月 19, 2012
ってことで hacker track も casual track も誰か書いてくれないかなー!?