Piotr Dobrogost
Piotr Dobrogost

Reputation: 42425

How can I delete variable in Template Toolkit?

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.

Upvotes: 4

Views: 1485

Answers (2)

Marco De Lellis
Marco De Lellis

Reputation: 1189

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 %]

Upvotes: 2

Piotr Dobrogost
Piotr Dobrogost

Reputation: 42425

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 %]

Upvotes: 2

Related Questions