[Templates] Flattening a hash

Andy Wardley abw@wardley.org
Fri, 17 Feb 2006 08:23:00 +0000


Bill Moseley wrote:
> I'm generating an option list.  The "options" method returns an
> array ref of hashes.
> 
> But TT flattens it when there's only one element in the array.

Hi Bill,

I suspect your options method is returning a list of hashes, rather than
a reference to a list of hashes.

    return \@hashes;     # good
    return  @hashes;     # bad

In the first case you should always get what you expect.  In the second
case, TT will notice if you return multiple values (e.g. @hashes > 1)
and fold it into a list reference.  But if there's only one item then
TT will assume you meant to return that and won't fold it into a list.

This example illustrates:

    use strict;
    use warnings;
    use Template;

    my @options = ( { value => 1, label => 'Foo' } );
    my $ttvars  = {
        good => sub { return \@options },
        bad  => sub { return  @options },
    };
    Template->new->process(\*DATA, $ttvars);
  
    __DATA__
    Good:
    [% FOR opt IN good -%]
    <option value="[% opt.value %]">[% opt.label %]</option>
    [% END -%]

    Bad:
    [% FOR opt IN bad -%]
    <option value="[% opt.value %]">[% opt.label %]</option>
    [% END %]

The output is:

    Good:
    <option value="1">Foo</option>

    Bad:
    <option value="Foo"></option>
    <option value="1"></option>

HTH
A