Looking at Template::Manual::VMethods section of the Template Toolkit manual I don't see any method doing this. Also assigning undef
to variable doesn't work - variable.defined
returns true after the fact.

- 41,292
- 40
- 236
- 366
2 Answers
Well, googling "delete variable" site:mail.template-toolkit.org/pipermail/templates/
brought the question [Templates] Can I “DELETE some_var”? from Felipe Gasper with two answers from Petr Danihlik. Petr suggests:
[% SET foo = 1 %]
[% IF foo.defined %] defined1 [% END %]
[% PERL %]
delete($stash->{foo});
[% END %]
[% IF foo.defined %] defined2 [% END %]

- 41,292
- 40
- 236
- 366
-
Interesting. When we use references coming from the stash ( Catalyst? ) in TT templates, we write `[% var %]` instead of `[% stash.var %]`. I was wondering if you have already tried messing with `[% stash.var %]`. – Marco De Lellis Sep 29 '11 at 12:24
-
Referencing variable this way doesn't bring any new possibilities, does it? I can't use `PERL` directive as shown in the answer I found because TT processor I use doesn't allow inline Perl. – Piotr Dobrogost Sep 29 '11 at 15:22
I looked at Catalyst::View:TT code, in order to understand variables context.
The following subroutine, which I summarized a little bit does the rendering work:
sub render {
my ( $self, $c, $template, $args ) = @_;
# [...]
my $output; # Template rendering will end here
# Variables interpolated by TT process() are passed inside an hashref
# as copies.
my $vars = {
( ref $args eq 'HASH' ? %$args : %{ $c->stash() } ),
$self->template_vars( $c )
};
# [...]
unless ( $self->template->process( $template, $vars, \$output ) ) {
# [ ... ]
}
# [ ... ]
return $output;
}
TT process()
is called with copies of variables in $c->stash
, so why do we need to mess with $c->stash
to get rid of a local copy? Maybe we don't.
Moreover, TT define()
VMethod, like other methods, seem to have been built for lists. Scalars are auto-promoted to single element list when a VMethod is called on them: maybe for this reason the IF test returns always true.
I did some tests with variables carrying references to DBIx::Class::ResultSet
objects, and this seems to work while testing for a variable:
[%- resultset_rs = undef %]
[%- IF ( resultset_rs ) %]
<h3>defined</h3>
[%- END %]
The first line deletes the variable, and the second does proper test.
UPDATE
If you can add EVAL_PERL => 1
flag in your Catalyst View, inside config()
argumets,
__PACKAGE__->config({
# ...
EVAL_PERL => 1
});
then you can use [% RAWPERL %]
directive in templates, which gives you direct access to the Template::Context
object: then you can delete vars and .defined()
VMethod does the right thing.
[%- RAWPERL %]
delete $context->stash->{ 'resultset_rs' };
[%- END %]
[%- IF ( resultset_rs.defined ) %]
<h3>defined: [% resultset_rs %]<h3>
[%- ELSE %]
<h3>undefined: [% resultset_rs %]<h3>
[%- END %]

- 1,169
- 6
- 10
-
What kind of variable is that you're trying to undef? An array, a scalar? – Marco De Lellis Sep 29 '11 at 13:58
-
And doesn't it work? Can you post a portion of your code with unexpected behavior? – Marco De Lellis Sep 29 '11 at 14:54
-
It doesn't work as it doesn't test if a variable is defined but if it's true. My variable denotes size in pixels so it can have value `0` which is false in boolean context. – Piotr Dobrogost Sep 29 '11 at 15:13
-
The documentation section **Directives/RAWPERL** says: _The Template Toolkit parser reads a source template and generates the text of a Perl subroutine as output. It then uses eval() to evaluate it into a subroutine reference_. Maybe this prevents direct access to variables hashref unless we place some code in `[% RAWPERL %]` block. – Marco De Lellis Sep 29 '11 at 16:08
-
How is the code in your update different from the one shown in my answer? – Piotr Dobrogost Sep 29 '11 at 19:00
-
Well, you can find the ( little ) difference written in the manual, where it says that `[% RAWPERL %]` is more efficient than `[% PERL %]`: _The RAWPERL directive allows you to write Perl code that is integrated directly into the generated Perl subroutine text. It is evaluated once at compile time and is stored in cached form as part of the compiled template subroutine. This makes RAWPERL blocks more efficient than PERL blocks._ I think you should accept your own answer which has been a good opportunity to look under the cover of TT. – Marco De Lellis Sep 30 '11 at 05:52