Как я могу форсировать контекст списка в Template Toolkit с помощью RDBO? - PullRequest
2 голосов
/ 07 января 2010

У меня есть плагин 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 ]

6 голосов
/ 07 января 2010

Нашел это в списке рассылки TT:

http://lists.template -toolkit.org / pipermail / шаблоны / 2009-декабрь / 011061.html

похоже, что у ".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];
    },
);
3 голосов
/ 07 января 2010

Это не совсем то, что вам нужно, но не могли бы вы изменить плагин 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;
}
...