2017-05-03 3 views
0
でのテンプレートツールキットで無名ハッシュ

ある配列項目:アクセスのPerl

my $gr = My::Model::Group->new(id => $gra->gr_id); 
$gra = My::Model::Group::Admin->new(id => $gra->id); 
push(@$groups, {$gr => $gra}); 

の@ $グループアレイでは、私は匿名を保存しますキー要素がグループオブジェクトであり、値要素がそのグループオブジェクトの管理者であるハッシュ。それから私は、管理者がログインすることができますさまざまなグループのリストを表示するテンプレート、そのために私はこのコードを持っているに:

[%- FOREACH gr IN groups -%] 
    <li><input type="radio" name="group" value="[% gr.id %]">[% gr.name %]</input></li> 
[%- END -%] 

私はパートナーのpが右ではなく、あなたに何を示すことであることを知っています私は達成したい。テンプレートコードに関する提案はありますか?

+0

FOREACH item IN listは正しいです。しかし、あなたはそれらを再編成したいのですか?これはExcelのピボットのようなものです。あなたは '{1 => 'foo'、2 => 'bar'、3 => 'foo'}'のようなものを持っていて、 'foo'は' 1,3 'を、 'bar'は' 2 '。私は理解しましたか? – simbabque

+0

はい、そうです。あなたはそれが絶対に正しいことを得た – Albert

+0

複数の管理者がいますか?私はまだ期待される出力を理解していない。 – simbabque

答えて

3

duskwuff already explains in their answer。私の答えはそれに基づいています。

代わりに、配列の配列があり、各内部配列にオブジェクトのペアがあるとします。私は説明するためにMooクラスを作成しました。

package My::Model::Group; 
use Moo; 
has [qw/id name/] => (is => 'ro'); 

package My::Model::Group::Admin; 
use Moo; 
has [qw/id name/] => (is => 'ro'); 

package main; 

my $groups = [ 
    [ 
     My::Model::Group->new(id => 1, name => 'group1') => 
      My::Model::Group::Admin->new(id => 1, name => 'foo') 
    ], 
    [ 
     My::Model::Group->new(id => 2, name => 'group2') => 
      My::Model::Group::Admin->new(id => 1, name => 'foo') 
    ], 
    [ 
     My::Model::Group->new(id => 3, name => 'group3') => 
      My::Model::Group::Admin->new(id => 1, name => 'bar') 
    ], 
    [ 
     My::Model::Group->new(id => 4, name => 'group4') => 
      My::Model::Group::Admin->new(id => 1, name => 'foo') 
    ], 
]; 

4つのペアがあります。 2人の管理者、4人のグループ。グループのうちの3つはfoo adminに属し、1つはbarに属します。テンプレートを見てみましょう。

use Template; 

my $tt = Template->new(); 
$tt->process(\*DATA, { groups => $groups }, \my $output) 
    or die $tt->error; 

print $output; 
__DATA__ 
[%- FOREACH item IN groups -%] 
    [%- DEFAULT by_admin.${item.1.name} = [] -%] 
    [%- by_admin.${item.1.name}.push(item.0) -%] 
[%- END -%] 

[%- FOREACH admin IN by_admin.keys.sort -%] 
    [%- FOREACH group IN by_admin.$admin -%] 
     [%- admin %] -> [% group.id %] 

    [%- END -%] 
[%- END -%] 

明らかに、該当する部分はDATAセクションです。アレイデータ構造を管理者を持つハッシュに再編成し、各グループを管理スロットの1つにソートする必要があります。

変数by_adminを作成する必要はありません。暗黙的にグローバルに作成されます。しかし、私たちは$by_admin->{$item[0]->name}のデフォルト値を設定する必要があります(わかりやすくするためにPerl構文を使用しています)。 Template Toolkitはautovivificationを知らず、the DEFAULT keyword//= assignment operator in Perlと似ています。

我々はby_name内部キーitem.1.nameとハッシュリファレンス要素内先ほど作成した配列リファレンスへitemのその後push最初の要素(それはまだ存在していなかった場合)することができます。

準備が整ったら、残りは単純なループにすぎません。 sortedkeysby_adminに反復し、そのキーの後ろにある配列refを反復処理します。しかし、あなたのコントローラでは代わりに、これは、テンプレートにない前処理を行うには理にかなって

bar -> 3 
foo -> 1 
foo -> 2 
foo -> 4 

は、ここでの出力です。通常のPerlコードでは、読みやすくする必要があります。私は簡潔にするためuse strictuse warningsを省略している

my %by_admin; 
for my $group (@$groups) { 
    push @{ $by_admin{ $group->[1]{name} } }, $group->[0]; 
} 

注意。

+0

そのコードのスニペットで私はそれを得た。どうもありがとう!あなたは私の一日を作った – Albert

+0

@Albert本当に重要な部分は 'DEFAULT'です。それは私が理解するのにしばらく時間がかかりました。 – simbabque

+1

あなたが言及したように、これはPerl(TTではない)で最もよく行われるので、Perlコードを追加しました。 – ikegami

3

これを可能にするには、コードを大幅に修正する必要があります。

Perlハッシュのキーは、文字列であり、スカラーではありません。ハッシュのキーとして文字列ではないものを使用すると(例えば、式{ $gr => $gra }$grは文字列に補間したかのように文字列に変換されます)""を明示的にオーバーロードしていない限り - 実際には、元のオブジェクトは、おそらくゴミだった

"My::Model::Group=HASH(0x1234567890)" 

この文字列は、元のオブジェクトに変換することができません。My::Model::Groupオブジェクト上のオペレータは、キーの線に沿って文字列リテラルとして格納されてしまいます範囲外になるとすぐに収集され、存在しなくなりました。

ペアを配列として格納することを検討してください代わりに、彼らはシリアル化された取得し、あなたがオブジェクトネスを失うことになるとしてあなたがハッシュキーとしてオブジェクトを使用することはできません

push @$groups, [$gr, $gra]; 
+0

でも、テンプレートの$ grのIDにアクセスするにはどうしたらいいですか? – Albert

関連する問題