atom feed8 messages in org.template-toolkit.templatesRe: [Templates] Tests for defined nes...
FromSent OnAttachments
Todd RinaldoNov 13, 2008 10:58 am 
Sean McAfeeNov 13, 2008 12:04 pm 
Josh RosenbaumNov 13, 2008 12:42 pm 
Todd RinaldoNov 13, 2008 3:06 pm 
Kelly ThompsonNov 13, 2008 3:07 pm 
Todd RinaldoNov 13, 2008 3:08 pm 
Sean McAfeeNov 13, 2008 3:25 pm 
Andy WardleyNov 13, 2008 11:58 pm 
Subject:Re: [Templates] Tests for defined nested hash
From:Sean McAfee (eef@gmail.com)
Date:Nov 13, 2008 3:25:26 pm
List:org.template-toolkit.templates

On Thu, Nov 13, 2008 at 3:09 PM, Todd Rinaldo <tod@null.net> wrote:

On Thu, Nov 13, 2008 at 2:05 PM, Sean McAfee <eef@gmail.com> wrote:

On Thu, Nov 13, 2008 at 10:58 AM, Todd Rinaldo <tod@null.net> wrote:

My question: Is there any easy way to make a recursive block that can test if an unpredictably deep hash is defined?

Perhaps, but it would be easier to write a routine in Perl:

sub nested { my ($hash, @keys) = @_; for my $key (@keys) { return if ref $hash ne 'HASH' || !exists $hash->{$key}; $hash = $hash->{$key}; } return 1; }

Provide the function to your template, and then you could say:

[% NEXT IF !nested(hash, 'fi', 'fo', 'fum', 'bar') %]

Alternately, you could make it a new hash vmethod.

Sean, a perl routine would be easier, but my restriction is my inability to turn off {TOLERANT => 0, EVAL_PERL => 0}.

The TOLERANT flag isn't really relevant to this situation, and the EVAL_PERL flag only applies to Perl code that's encountered within the body of a template. To see this, combine the following code with the nested() function above:

my %hash = ( a => { b => { c => { d => 1 } } } ); my $template = Template->new({ TOLERANT => 0, EVAL_PERL => 0 }); $template->process( \ '[% nested(hash, "a", "b", "c", "d") %]', { nested => \&nested, hash => \%hash } ) or die $template->error;

It prints "1".

It sounds like the vmethod is the way to go, but I'm not clear how to

do that can you point me to where I could find an example?

See:

http://tt2.org/docs/manual/VMethods.html#section_Defining_Custom_Virtual_Methods

In short, you can say:

use Template::Stash; $Template::Stash::HASH_OPS->{nested} = \&nested;

Then you can say

[% hash.nested("a", "b", "c", "d") %]

If you go this route, you no longer need to supply "nested" as a template variable, as in my original example.

--Sean