TT の VMethods のせいで,たまにはまりがちなこと

VMethods の予約語のせいではまる

directory という名のハッシュが items という子項目を持っていて

$stash->{directory} = {
  type => 'files',
  items => [
    'file_a',
    'file_b',
    'file_c',
  ],
};

それを列挙して表示したい場合に,

<h1>[% directory.type %]</h1>
<ul>
[% FOREACH item IN directory.items -%]
  <li>[% item.name %]</li>
[% END -%]
</ul>

みたいなテンプレートを書いたりします。上記のように想定済みのハッシュを与えるのなら動くのですが,

$stash->{directory} = {
  type => 'empty directory',
  # items is not defined
};

のように,items を設定しないでおいてもなぜか空項目が表示されたりします。
これは items という名前の VMethod が定義されている(参照)ためです。

items なんてまぎらわしいキーをハッシュにつけるなといいたいところですが,どうしてもそのまま使いたいのであれば,item という VMethod を利用して,

<h1>[% directory.type %]</h1>
<ul>
[% FOREACH item IN directory.item('items') -%]
  <li>[% item.name %]</li>
[% END -%]
</ul>

のようにするとうまくいきます。

undef に対する VMethod はない

文字列がブランクであれば代わりに「(未入力)」と表示する SCALAR VMethod 「empty_msg」を定義してやったとして,

[% your_name.empty_msg %]

と書いても,your_name が stash になかったり undef だったりするときには,ブランクになってしまいます。これは,表題のとおり,VMethod は undef 値にたいして呼び出されないからです(そもそもどのタイプの VMethod を呼び出せばいいのかわからないし)。

文字列に対してとわかっているのであれば,VMethod ではなく Filter として実装すれば

[% your_name | empty_msg %]

いいと思います。