続き。
Viewを分離する
その前にJSON出力をサンプルではしているけれど、愛で割ります。
というわけで、きっちり一枚岩のはてブタグ(最新エントリ)検索ができたので、次のSTEPへ。
MVC渾然一体となったプログラムを分割していく。
まずはView!
これなら分かるし、知ってるし、使ったことがある!
と思ってるけどここは焦らず写経っぽく。
じゃあまずはTemplateで使う用のHTMLをば。
index.html
<html> <head> <title>Hatena Tag Search</title> </head> <body> <h1>Hatena Tag Search</h1> <form method="get"> <input type="text" name="search_tag" /> <input type="submit" value="Search" /> </form> </body> </html>
result.html
<html> <head> <title>Hatena Tag Search - Result</title> </head> <body> <h1>Hatena Tag Search</h1> <form method="get"> <input type="text" name="search_tag" value="[% search_tag | html %]" /> <input type="submit" value="Search" /> </form> <h2>Result ([% result.size %])</h2> <ul> [% FOREACH entry IN result -%] <li><a href="[% entry.link %]">[% encode(entry.title) | html %]</a></li> [% END -%] </ul> </body> </html>
覚えたこと。
resultは配列リファレンス。
[% -%]にすると改行が減らせる。
html とか | uri とかはフィルタで、いい感じにHTMLしてくれる。 |
で、問題のViewを切り離したcgi。
tag_search3.cgi
#!/usr/local/bin/perl # tag_search3.cgi use strict; use warnings; use CGI qw/:standard/; use LWP::UserAgent; use Params::Validate qw/:all/; use URI; use XML::Simple; use Encode qw/encode/; use Template; my $HATENA_TAG_API = "http://b.hatena.ne.jp/t/"; my $q = CGI->new; print header( -type => 'text/html', -charset => 'utf-8' ); # Which Template ? my $tmpl = $q->param('search_tag') ? '/Users/rightgo09/Script/Perl/template/result.html' : '/Users/rightgo09/Script/Perl/template/index.html' ; # Substitution Data my $vars = $q->param('search_tag') ? { result => search_hatena_tag($q->param('search_tag'))->{item}, encode => sub { encode('utf8', +shift) }, search_tag => $q->param('search_tag') } : {} ; # Rendering TT my $template = Template->new(ABSOLUTE => 1); $template->process($tmpl, $vars, \my $out) or die $template->error; print $out; sub search_hatena_tag { my ($query) = validate_pos(@_, { type => SCALAR }); # Hatena Tag RSS API my $uri = URI->new($HATENA_TAG_API.$query); $uri->query_form( sort => 'eid', mode => 'rss' ); my $ua = LWP::UserAgent->new; my $res = $ua->get($uri); die $res->status_line if $res->is_error; return _parse_data(\$res->content); } sub _parse_data { my ($xml_ref) = validate_pos(@_, { type => SCALARREF }); my $parser = XML::Simple->new; my $data; eval { $data = $parser->XMLin($$xml_ref) }; die $@ if $@; return $data; } __END__
下半分くらいは前と一緒。
だけど、やっぱりHTMLを直接出していないだけ、すっきり見える。
ただその分置き換え用のデータをごちゃごちゃしなくちゃいけなくて、まだまだその辺は堅苦しい。
覚えたこと。
テンプレートに絶対パスを渡すならTemplate->newでABSOLUTE=>1が要る。