HTML::Shakan で choices が消えて困ってるの巻
[追記:2010-07-17] さっそく対応してもらいましたので、HTML::Shakan 0.06 からこの記事のテストは通るようになりました
はい、なんかタイトルで言い切った感がありますけど、だらだらと説明しちゃいますよ!
HTML::Shakan とは
id:tokuhirom さん作で Django のフォームっぽい感じの素敵な form generator / validator という感じのものです。
詳しくは日本語のドキュメント付属してるから、そっちを読むと良いよ。
どういう時に困るか
HTML::Shakan の SYNOPSIS にあるように、毎回 form を定義するような使い方をするならば困らないのですが、HTML::Shakan::Declare で form を作って、使うときは get して使いまわすような場合に困ったことになります。
とかいってもよく伝わらないでしょうから、テストケースを書きました。
{ package My::Form; use HTML::Shakan::Declare; form 'my_form' => ( ChoiceField( name => 'foo', widget => 'select', choices => [qw/1 one 2 two 3 three/], ), ChoiceField( name => 'bar', widget => 'radio', choices => [qw/1 one 2 two 3 three/], ), ); } { package main; use strict; use warnings; use CGI; use Test::More; is form('my_form')->render(), form('my_form')->render(); sub form { my $name = shift; return My::Form->get( $name => ( request => CGI->new(), ), ); } done_testing; }
現状の HEAD ですとこのテストはこけてしまいます。
なぜ消えたし
HTML::Shakan::Widgets::Simple の中で choices を消すような操作をしているからですね。
widget_select() と widget_radio() がそれにあたります。
結局どうすれば
そもそも Widget は差し替え可能な作りになっているので、そこを差し替えれば良いのですが、Widget で form の定義が書き換えられて嬉しいケースっていうのが特に思い浮かばなかったので、僕は以下のような感じで凌いでいます。*1
diff --git a/lib/HTML/Shakan/Declare.pm b/lib/HTML/Shakan/Declare.pm index 3edf8ac..45249dd 100644 --- a/lib/HTML/Shakan/Declare.pm +++ b/lib/HTML/Shakan/Declare.pm @@ -3,6 +3,7 @@ use strict; use warnings; use base 'Exporter'; use HTML::Shakan (); +use Storable qw/dclone/; our @EXPORT = qw(form get); @@ -23,7 +24,7 @@ sub get { my ($class, $name, %args) = @_; $class = ref $class || $class; return HTML::Shakan->new( - fields => $FORMS->{$class}->{$name}, + fields => dclone $FORMS->{$class}->{$name}, %args, ); }
というわけで
良かったら取り込んでもらえると嬉しいです > id:tokuhirom さん
なんか誤解していたり、普通こうやるよね!みたいなのあったら教えてください!
*1:実際は mokey patch ですよ