如何使用RDBO强制模板工具包中的列表上下文?

时间:2010-01-06 21:45:08

标签: perl template-toolkit rose-db-object

我有一个TT插件,可以完成琐碎的独特ID:

sub get_unique_uid_tt {
  my ( $classname, $o ) = @_;

  my %h;

  foreach my $item ( @{$o} ) {
    unless ( exists $h{ $item->id } ) {
      $h{ $item->id } = 1;
    }
  }

  return keys %h;
}

模板调用只是:

[% Namespace.get_unique_uid_tt( data.users ) %]

和“data”是一个RDB对象,用户是其关系之一。我已经验证“.users”直接在Perl中返回一个列表,无论该关系是否包含一个或多个元素。

但是,TT似乎返回单元素列表的元素,同时正确返回多个元素的列表。

我查了一下,发现你可以用“.list”强制列表上下文:

[% Namespace.get_unique_uid_tt( data.users.list ) %]

这对于单元素列表不起作用,正如Data :: Dumper所揭示的那样:

$VAR1 = [
      {
        'value' => 1,
        'key' => '__xrdbopriv_in_db'
      },
      {
        'value' => bless(
         ... snip ...
         ),
        'key' => 'db'
      },
      {
        'value' => '1',
        'key' => 'id'
      }
];

而不是预期的

 $VAR1 = [
     bless( {
             '__xrdbopriv_in_db' => 1,
             'id' => '1',
             'db' => ... snip ...
     }, 'DataClass' )
 ];

TT中有没有其他简单的方法来获取对象列表,即使在单元素列表上也是如此? (一种方法是重写函数,但不重写函数)

2 个答案:

答案 0 :(得分:6)

在TT邮件列表上找到了这个:

http://lists.template-toolkit.org/pipermail/templates/2009-December/011061.html

似乎TT的“.list”在将对象转换为列表时遇到问题,而不仅仅是RDBO。

建议是做一个vmethod:

$Template::Stash::LIST_OPS->{ as_list } = sub {
   return ref( $_[0] ) eq 'ARRAY' ? shift : [shift];
};

我将此添加到我的上下文对象(同样的想法):

$context->define_vmethod(
    'list',
    'as_list',
    sub {
        return ref( $_[0] ) eq 'ARRAY' ? shift : [shift];
    },
);

答案 1 :(得分:3)

这不是你想要的,但你可以改变TT插件来处理列表和单个项目吗?

sub get_unique_uid_tt {
  my ( $classname, $o ) = @_;

  my %h;

  if (ref $o eq 'ARRAY') {
    foreach my $item ( @{$o} ) {
      unless ( exists $h{ $item->id } ) {
        $h{ $item->id } = 1;
      }
    }
  }
  else {
      return ($o->id);
  }

  return keys %h;
}