Как я могу форсировать контекст списка в Template Toolkit с помощью RDBO?
У меня есть плагин TT, который делает тривиальные уникальные идентификаторы:
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 ) %]
и "данные" - это объект 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' )
];
Есть ли какой-либо другой простой способ в ТТ получить список объектов, даже в одноэлементных списках? (Один из подходов - переписать функцию, но тот, который не является предпочтительным)
2 ответа
Нашел это в списке рассылки TT:
http://lists.template-toolkit.org/pipermail/templates/2009-December/011061.html
Похоже, что ".list" ТТ имеет проблемы с преобразованием объектов в списки, а не только в RDBO.
Предлагаем сделать метод:
$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];
},
);
Это не совсем то, что вам нужно, но не могли бы вы изменить плагин 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;
}