tokuhirom's Journal tokuhirom's use Perl Journal en-us use Perl; is Copyright 1998-2006, Chris Nandor. Stories, comments, journals, and other submissions posted on use Perl; are Copyright their respective owners. 2012-01-25T02:33:02+00:00 pudge Technology hourly 1 1970-01-01T00:00+00:00 tokuhirom's Journal I wrote Test::TCP <p>I've wrote Test::TCP today.</p><p>If you write tests with Test::TCP, easy to write the test, that using TCP socket.</p><p>follow is example code.</p><p> &nbsp; &nbsp; &nbsp; &nbsp; use warnings;<br> &nbsp; &nbsp; &nbsp; &nbsp; use strict;</p><p> &nbsp; &nbsp; &nbsp; &nbsp; package MyEchoServer;<br> &nbsp; &nbsp; &nbsp; &nbsp; use IO::Socket::INET;</p><p> &nbsp; &nbsp; &nbsp; &nbsp; sub new {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my ($class, $port) = @_;</p><p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my $sock = IO::Socket::INET-&gt;new(<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LocalPort =&gt; $port,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LocalAddr =&gt; '',<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Proto =&gt; 'tcp',<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Listen =&gt; 5,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Type =&gt; SOCK_STREAM,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ) or die "Cannot open server socket: $!";<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bless { sock =&gt; $sock }, $class;<br> &nbsp; &nbsp; &nbsp; &nbsp; }</p><p> &nbsp; &nbsp; &nbsp; &nbsp; sub run {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my $self = shift;</p><p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (my $remote = $self-&gt;{sock}-&gt;accept) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (my $line = ) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print {$remote} $line;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br> &nbsp; &nbsp; &nbsp; &nbsp; }</p><p> &nbsp; &nbsp; &nbsp; &nbsp; package main;<br> &nbsp; &nbsp; &nbsp; &nbsp; use strict;<br> &nbsp; &nbsp; &nbsp; &nbsp; use warnings;<br> &nbsp; &nbsp; &nbsp; &nbsp; use Test::More tests =&gt; 1;<br> &nbsp; &nbsp; &nbsp; &nbsp; use Test::TCP;<br> &nbsp; &nbsp; &nbsp; &nbsp; use IO::Socket::INET;</p><p> &nbsp; &nbsp; &nbsp; &nbsp; test_tcp(<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; client =&gt; sub {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my $port = shift;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my $sock = IO::Socket::INET-&gt;new(<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PeerPort =&gt; $port,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PeerAddr =&gt; '',<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Proto =&gt; 'tcp'<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ) or die "Cannot open client socket: $!";<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print {$sock} "foo\n";<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my $res = ;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; is $res, "foo\n";<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; server =&gt; sub {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my $port = shift;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MyEchoServer-&gt;new($port)-&gt;run;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },<br> &nbsp; &nbsp; &nbsp; &nbsp; );</p><p>and repository is here:</p><p><a href=""></a></p> tokuhirom 2008-08-17T06:30:13+00:00 journal Perl5 VM Golf <p>I've released Acme::PerlVMGolf.<br>This is new golf rule for perl hackers<nobr> <wbr></nobr>:)</p><p>PerlVMGolf's rule is very simple.follow is the rule:</p><p> &nbsp; * write the code for the score<br> &nbsp; * your score is sum of your op code number<br> &nbsp; * short perl code is good</p><p>Are you right?</p><p>You can calcurate your score by Acme::PerlVMGolf(I've uploaded to CPAN now, and you can get from our svn repos</p><p> &nbsp; &nbsp; perl -MAcme::PerlVMGolf -e '0'<br> &nbsp; &nbsp; hit: 177op<br> &nbsp; &nbsp; hit: 174op<br> &nbsp; &nbsp; hit: 178op<br> &nbsp; &nbsp; Your perl is : 5.8.8<br> &nbsp; &nbsp; Your score is : 529op</p><p>I give first challenge : how to implement 1000op?</p> tokuhirom 2008-06-23T11:12:11+00:00 journal Test::Snippet - Test interactive Perl examples <tt>I've wrote Test::Snippet.<br><br> <br><nobr> <wbr></nobr> This is a port of Python's doctest.<br>doctest is :<br><br>1. use your module at<br>2. copy and paste to pod<br>3. run tests.<br><br>that's all.<br><br>follow is example code:<br><br>&nbsp; &nbsp; your code here.<br><br>&nbsp; &nbsp; =head1 NAME<br><br>&nbsp; &nbsp; Acme::Test - testing acme<br><br>&nbsp; &nbsp; =head1 DESCRIPTION<br><br>&nbsp; &nbsp; blah blah blah<br><br>&nbsp; &nbsp; =begin test<br><br>&nbsp; &nbsp; $ 3+2<br>&nbsp; &nbsp; 5<br>&nbsp; &nbsp; $ [2,5,5,{foo =&gt; 'bar'}]<br>&nbsp; &nbsp; $ARRAY1 = [<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ( 5 ) x 2,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { foo =&gt; 'bar' }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ];<br><br>&nbsp; &nbsp; =end test<br><br>&nbsp; &nbsp; =cut<br><br>&nbsp; &nbsp; something.. something..<br><br>&nbsp; &nbsp; =head1 SEE ALSO<br><br>&nbsp; &nbsp; ME!<br></tt> tokuhirom 2008-06-12T04:05:50+00:00 journal Moose::Role + overload <tt>follow code does not works.<br><br>&nbsp; package MyApp::Role::Stringify;<br>&nbsp; use overload<br>&nbsp; &nbsp; q{""} =&gt; sub { shift-&gt;stringify }<br>&nbsp;<nobr> <wbr></nobr>;<br>&nbsp; requires 'stringify';<br><br>&nbsp; package MyApp;<br>&nbsp; with 'MyApp::Role::Stringify';<br>&nbsp; has dat ( is =&gt; 'ro', isa =&gt; 'Str' );<br>&nbsp; sub stringify { shift-&gt;dat }<br><br>because, the architecture of is<br><br>&nbsp; export method named '()'<br>&nbsp; export method named '(""'<br><br>Moose::Role applies coderefs, that defined at Role.Exported methods are not import to applicant.<br><br>one way to resolve this problem is:<br><br>&nbsp; &nbsp; package MyApp::Role::Stringify;<br>&nbsp; &nbsp; use Moose::Role;<br>&nbsp; &nbsp; __PACKAGE__-&gt;meta-&gt;add_package_symbol('&amp;()' =&gt; sub { }); # dummy<br>&nbsp; &nbsp; __PACKAGE__-&gt;meta-&gt;add_package_symbol('&amp;(""' =&gt; sub { shift-&gt;stringify });<br><br>but, this is not so smart<nobr> <wbr></nobr>:( this is Hentai way(hentai means tricky in japanese)<br></tt> tokuhirom 2008-06-04T02:20:03+00:00 journal Moose talk in Japan <tt>hakobe-san makes presentation about mooooooose at<br><br>slide is here:<br><br>moooooooooooooooooooose!</tt> tokuhirom 2008-06-02T23:40:26+00:00 journal MooseX::Plaggerize <tt>### DESCRIPTION<br><br>I want to use Plagger style plugins architecture with Moose.Therefore, I created MooseX::Plaggerize!<br><br>svn repos is here:<br><br>### SYNOPSIS<br><br>&nbsp; &nbsp; # in main<br><br>&nbsp; &nbsp; my $c = Your::Context-&gt;new;<br>&nbsp; &nbsp; $c-&gt;load_config('config.yaml'); # feature of MooseX::Plaggerize::ConfigLoader<br>&nbsp; &nbsp; $c-&gt;load_plugin('HTMLFilter::StickyTime');<br>&nbsp; &nbsp; $c-&gt;load_plugin({module =&gt; 'HTMLFilter::DocRoot', config =&gt; { root =&gt; '/mobirc/' }});<br>&nbsp; &nbsp; $c-&gt;run();<br><br>&nbsp; &nbsp; package Your::Context;<br>&nbsp; &nbsp; use Moose;<br>&nbsp; &nbsp; with 'MooseX::Plaggerize', 'MooseX::Plaggerize::ConfigLoader';<br><br>&nbsp; &nbsp; sub run {<br>&nbsp; &nbsp; &nbsp; &nbsp; my $self = shift;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; $self-&gt;run_hook('response_filter' =&gt; $args);<br>&nbsp; &nbsp; }<br><br>&nbsp; &nbsp; package Your::Plugin::HTMLFilter::StickyTime;<br>&nbsp; &nbsp; use strict;<br>&nbsp; &nbsp; use MooseX::Plaggerize::Plugin;<br><br>&nbsp; &nbsp; hook 'response_filter' =&gt; sub {<br>&nbsp; &nbsp; &nbsp; &nbsp; my ($self, $context, $args) = @_;<br>&nbsp; &nbsp; };<br><br>### CONCEPT<br><br> * Plugin architecture like Plagger<br> * Each plugin has own instance<br> * Each plugin can have own configuration<br><br>### What's difference with MooseX::Object::Pluggable?<br><br>yeah, I know MooseX::Object::Pluggable, ofcource.<br><br>MooseX::Object::Pluggable stands on Moose::Role and method modifiers.This is cool architecture.<br><br>But, this approach cannot use configuration like Plagger<nobr> <wbr></nobr>:(<br><br>therefore, I wrote MooseX::Plaggerize<nobr> <wbr></nobr>:)<br><br>###<nobr> <wbr></nobr>...<br><br>We would like to hear from you</tt> tokuhirom 2008-05-30T02:32:58+00:00 journal petit Moose movement in Japan <tt>some Japanese perl mongers are interested to Moose, and reading the code, and some bloggers are writing 'Yet Another Moose Cookbook' in Japanese<nobr> <wbr></nobr>:-)<br><br>- my japanese blog:<br>- yappo-san's :<br>- hidek-san's:<br><br>and,&nbsp; a few days after, many Japanese perl mongers listen a nothingmuch's Moose talk in YAPC::Asia 2008 in Japan!!<br><br>Will Moose popular in Japan?</tt> tokuhirom 2008-05-05T16:50:11+00:00 journal scraping sibling nodes by Web::Scraper. <tt>Web::Scraper is not good at some case. likes follow...<br><br>&nbsp; &lt;div class="author"&gt;miyagawa&lt;/div&gt;<br>&nbsp; &lt;div class="module"&gt;Web::Scraper&lt;/div&gt;<br>&nbsp; &lt;div class="author"&gt;hanekomu&lt;/div&gt;<br>&nbsp; &lt;div class="module"&gt;Dist-Joseki&lt;/div&gt;<br><br>This is not a tree structure.. hmm... Web::Scraper dependes on the tree structure, isn't it?<br><br>but, XPath is swiss army chainsaw.<br><br>&nbsp; scraper {<br>&nbsp; &nbsp; process '//div[@class="author"]', 'modules[]', scraper {<br>&nbsp; &nbsp; &nbsp; process '/.', 'author', 'TEXT';<br>&nbsp; &nbsp; &nbsp; process '/following-sibling::div[1][@class="module"]', 'title',&nbsp; 'TEXT';<br>&nbsp; &nbsp; }<br>&nbsp; };<br><br>but, this code is doesn't works.scraper cannot support this way.<br><br>If Web::Scraper supports this feature, you can be scraping from '', '', or many web sites more easily.<br><br>follow is the dirty and quick patch for this problem.<br><br></tt> tokuhirom 2007-11-23T02:05:19+00:00 journal I wrote Test::ShellPerl <tt>I wrote Test::ShellPerl.<br><br>This module likes doctest@python.<br>&lt;blockquote&gt;<br>The doctest module searches for pieces of text that look like interactive Python sessions, and then executes those sessions to verify that they work exactly as shown.<br>&lt;/blockquote&gt;<br><br>Here's a small example module of doctest@python:<br>&lt;pre&gt;<br>"""<br>This is the "example" module.<br><br>&gt;&gt;&gt; factorial(5)<br>120<br>"""<br>def factorial(n):<br>&nbsp; &nbsp; """Return the factorial of n, an exact integer &gt;= 0.<br><br>&nbsp; &nbsp; If the result is small enough to fit in an int, return an int.<br>&nbsp; &nbsp; Else return a long.<br><br>&nbsp; &nbsp; &gt;&gt;&gt; [factorial(n) for n in range(6)]<br>&nbsp; &nbsp; [1, 1, 2, 6, 24, 120]<br>&nbsp; &nbsp; &gt;&gt;&gt; [factorial(long(n)) for n in range(6)]<br>&nbsp; &nbsp; [1, 1, 2, 6, 24, 120]<br>&nbsp; &nbsp; &gt;&gt;&gt; factorial(30)<br>&nbsp; &nbsp; 265252859812191058636308480000000L<br>&nbsp; &nbsp; &gt;&gt;&gt; factorial(30L)<br>&nbsp; &nbsp; 265252859812191058636308480000000L<br>&nbsp; &nbsp; &gt;&gt;&gt; factorial(-1)<br>&nbsp; &nbsp; Traceback (most recent call last):<br>&nbsp; &nbsp; &nbsp; &nbsp;<nobr> <wbr></nobr>...<br>&nbsp; &nbsp; ValueError: n must be &gt;= 0<br><br>&nbsp; &nbsp; Factorials of floats are OK, but the float must be an exact integer:<br>&nbsp; &nbsp; &gt;&gt;&gt; factorial(30.1)<br>&nbsp; &nbsp; Traceback (most recent call last):<br>&nbsp; &nbsp; &nbsp; &nbsp;<nobr> <wbr></nobr>...<br>&nbsp; &nbsp; ValueError: n must be exact integer<br>&nbsp; &nbsp; &gt;&gt;&gt; factorial(30.0)<br>&nbsp; &nbsp; 265252859812191058636308480000000L<br><br>&nbsp; &nbsp; It must also not be ridiculously large:<br>&nbsp; &nbsp; &gt;&gt;&gt; factorial(1e100)<br>&nbsp; &nbsp; Traceback (most recent call last):<br>&nbsp; &nbsp; &nbsp; &nbsp;<nobr> <wbr></nobr>...<br>&nbsp; &nbsp; OverflowError: n too large<br>&nbsp; &nbsp; """<br><br>&nbsp; &nbsp; (snip the imprementation...<br>&lt;/pre&gt;<br><br>Now, you can get this feature at Perl, with Shell::Perl.<br><br>Shell::Perl is cool interactive interface for Perl.You can use this interface for follow:<br><br>&lt;pre&gt;<br>=pod<br><br>=head1 DESCRIPTION<br><br>This is just a simple example module.<br><br>=begin test<br><br>pirl @&gt; 3+2<br>5<br>pirl @&gt;<nobr> <wbr></nobr>:set out DD<br>pirl @&gt; [2,5,5,{foo =&gt; 'bar'}]<br>@var = (<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;5,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;5,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;'foo' =&gt; 'bar'<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;]<br>&nbsp; &nbsp; &nbsp; &nbsp;);<br><br>=end test<br><br>=cut<br>&lt;/pre&gt;<br>and run test then:<br>&lt;pre&gt;<br>ok 1 - 3+2<br>ok 2 - [2,5,5,{foo =&gt; 'bar'}]<br>1..2<br>&lt;/pre&gt;<br><br>You can get the this module at my japanese blog.<br><br></tt> tokuhirom 2007-07-16T11:26:05+00:00 journal Gearman::Taskset::Async <p>I wrote Gearman::Taskset::Async, the Gearman asynchronous taskset.</p><p>for example:<br> &nbsp; &nbsp; &nbsp; &nbsp; use Gearman::Client;<br> &nbsp; &nbsp; &nbsp; &nbsp; use Gearman::Taskset::Async;<br> &nbsp; &nbsp; &nbsp; &nbsp; my $client = Gearman::Client-&gt;new(job_servers =&gt; ['']);<br> &nbsp; &nbsp; &nbsp; &nbsp; my $ts = $client-&gt;new_async_task_set;<br> &nbsp; &nbsp; &nbsp; &nbsp; for (1..1000) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $ts-&gt;add_task("echo" =&gt; \$_, +{on_complete =&gt; sub {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; warn "COMPLETED";<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; warn "@_";<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, on_fail =&gt; sub {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; warn "FAILED";<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }});<br> &nbsp; &nbsp; &nbsp; &nbsp; }<br> &nbsp; &nbsp; &nbsp; &nbsp; $ts-&gt;run;</p><p>Gearman has asynchronous client(Gearman::Client::Async), is based on Danga::Socket.Danga::Socket imcompatible with mod_perl, because that uses class variables.</p><p>source code is here: <a href="">Gearman::Taskset::Async</a></p><p>oops. It's just a Gearman::Taskset::BulkBlocRequest?</p> tokuhirom 2007-05-06T10:56:51+00:00 journal I released Gearman Client/Worker written in Python. <p>Currently, gearman supports perl and ruby.I want to support Python!!Python is very sexy<nobr> <wbr></nobr>;-)</p><p>yeah, I wrote the Gearman Client/Worker in Python.</p><p>now, you can use:</p><p> &nbsp; &nbsp; &nbsp; &nbsp; * Perl:Client &#8594; gearmand &#8594; Python:Worker<br> &nbsp; &nbsp; &nbsp; &nbsp; * Python:Client &#8594; gearmand &#8594; Ruby:Worker</p><p>and more combination.</p><p>wow! It's wonderful(In Japanese: Yume-ga-hirogarain-Guuuu!!)</p><p>source code is here: <a href="">Gearman Python Code.</a></p> tokuhirom 2007-05-06T10:41:24+00:00 journal Sledge::Plugin::Inflate::DateTime <p>I think, generate DateTime instance from is very frequent and very painful.</p><p>Yes, I wrote the Sledge::Plugin::Inflate::DateTime.</p><p>You just write the</p><blockquote><div><p> <tt>package Your::Pages;<br>use Sledge::Plguin::Inflate;<br>use Sledge::Plguin::Inflate::DateTime;<br> &nbsp; <br>__PACKAGE__-&gt;add_inflate_rule_ymd('date'); </tt></p></div> </blockquote><p>then, you can inflate DateTime object easily.</p><blockquote><div><p> <tt>sub dispatch_foo {<br>&nbsp; my $self = shift;<br>&nbsp; $self-&gt;stash-&gt;{date} = $self-&gt;r-&gt;inflate('date');<br>}</tt></p></div> </blockquote><p>And, Sledge::Plguin::Inflate::DateTime and HTML::DateSelector go together!</p><blockquote><div><p> <tt>package Sledge::Plugin::Inflate::DateTime;<br>use strict;<br>use warnings;<br>use DateTime;<br> &nbsp; <br>sub import {<br>&nbsp; &nbsp; my $pkg = caller(0);<br> &nbsp; <br>&nbsp; &nbsp; no strict 'refs';<br>&nbsp; &nbsp; *{"$pkg\::add_inflate_rule_ymd"} = sub {<br>&nbsp; &nbsp; &nbsp; &nbsp; my ($class, $key, $datetime) = @_;<br>&nbsp; &nbsp; &nbsp; &nbsp; $datetime ||= 'DateTime';<br> &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; $class-&gt;add_inflate_rule(<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $key =&gt; sub {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my ( $self, ) = @_;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my %args;<br> &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $args{year}&nbsp; = $self-&gt;r-&gt;param("$key\_year");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $args{month} = $self-&gt;r-&gt;param("$key\_month");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $args{day}&nbsp; &nbsp;= $self-&gt;r-&gt;param("$key\_day");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ( $args{year} &amp;&amp; $args{month} &amp;&amp; $args{day} ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return $datetime-&gt;new(%args);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; );<br>&nbsp; &nbsp; };<br>}<br> &nbsp; <br>1;<br>__END__<br> &nbsp; <br>=head1 SYSNOPSIS<br> &nbsp; <br>&nbsp; &nbsp; package Your::Pages;<br>&nbsp; &nbsp; use Sledge::Plugin::Inflate::DateTime;<br> &nbsp; <br>&nbsp; &nbsp; # simple way<br>&nbsp; &nbsp; __PACKAGE__-&gt;add_inflate_rule_ymd('from');<br> &nbsp; <br>&nbsp; &nbsp; # you can use your customized DateTime class.<br>&nbsp; &nbsp; __PACKAGE__-&gt;add_inflate_rule_ymd('from' =&gt; 'Your::DateTime');</tt></p></div> </blockquote> tokuhirom 2006-12-02T06:52:04+00:00 journal I want to Sledge::Config-&gt;path_to. <p></p><p>I want to write tmpl_path with path_to in config.<br>Because, tmpl_path is a configuration variable.</p><blockquote><div><p> <tt>package Project::Config;<br>use strict;<br>use warnings;<br>use base qw/Sledge::Config/;<br>use Sledge::Plugin::PathTo;<br>use vars qw(%C);<br>*Config = \%C;<br> &nbsp; <br>$C{TMPL_PATH} = path_to('view');<br>1;</tt></p></div> </blockquote><p>and, next version of Sledge::Config::YAML will supports<br>path_to, likes Catalyst::Plugin::ConfigLoader::YAML.Follw is<br>example configuration file:</p><blockquote><div><p> <tt>common:<br>&nbsp; tmpl_path: __path_to('view')__</tt></p></div> </blockquote><p>Yeah, that's so cool.</p> tokuhirom 2006-11-19T14:30:33+00:00 journal implementation of Sledge::Plugin. <p></p><p>here is implementation.</p><blockquote><div><p> <tt>package Sledge::Plugin;<br>use strict;<br>use warnings;<br>use base qw/Class::Data::Inheritable/;<br> &nbsp; <br>__PACKAGE__-&gt;mk_classdata('methods');<br>__PACKAG E__-&gt;mk_classdata('hooks');<br> &nbsp; <br>sub import {<br>&nbsp; &nbsp; my $class = shift;<br>&nbsp; &nbsp; my $pkg = caler(0);<br> &nbsp; <br>&nbsp; &nbsp; # add methods<br>&nbsp; &nbsp; while (my ($name, $code) = each %{$class-&gt;methods || {}} ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; no stirct 'refs';<br>&nbsp; &nbsp; &nbsp; &nbsp; *{"$pkg\::$name"} = $code;<br>&nbsp; &nbsp; }<br> &nbsp; <br>&nbsp; &nbsp; # register hooks<br>&nbsp; &nbsp; $class-&gt;register_hooks( %{ $class-&gt;hooks || {} } );<br>}<br> &nbsp; <br>sub add_methods {<br>&nbsp; &nbsp; my ($class, %d) = @_;<br> &nbsp; <br>&nbsp; &nbsp; $class-&gt;methods(<br>&nbsp; &nbsp; &nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; %{ $class-&gt;methods || {} },<br>&nbsp; &nbsp; &nbsp; &nbsp; %d,<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; );<br>}<br> &nbsp; <br>sub register_hooks {<br>&nbsp; &nbsp; my ($class, %d) = @_;<br> &nbsp; <br>&nbsp; &nbsp; $class-&gt;hooks(<br>&nbsp; &nbsp; &nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; %{ $class-&gt;hooks || {} },<br>&nbsp; &nbsp; &nbsp; &nbsp; %d,<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; );<br>}<br> &nbsp; <br>1;</tt></p></div> </blockquote> tokuhirom 2006-11-17T07:25:50+00:00 journal I released Sledge::Plugin::Pager 0.01 on CPAN. <p>I wrote the Sledge::Plugin::Pager.</p><p>I want easy to write the paging, because every index page needs<br>paginate, in prgmatic web application.</p><p>A normal paginate dispatcher code is:</p><blockquote><div><p> <tt>sub dispatch_index {<br>&nbsp; my $self = shift;<br>&nbsp; $self-&gt;stash-&gt;{pager} = Your::Data::CD-&gt;pager(20, $self-&gt;r-&gt;param('page') || 1);<br>&nbsp; $self-&gt;stash-&gt;{cds}&nbsp; &nbsp;= $self-&gt;stash-&gt;{pager}-&gt;retrieve_all;<br>}</tt></p></div> </blockquote><p>follow is equevalent code with Sledge::Plugin::Pager.</p><blockquote><div><p> <tt>use Sledge::Plugin::Pager;<br>sub dispatch_index {<br>&nbsp; my $self = shift;<br>&nbsp; $self-&gt;pager('Your::Data::CD')-&gt;retrieve_all;<br>}</tt></p></div> </blockquote><p>Yeah, happy paging!</p> tokuhirom 2006-11-05T15:32:34+00:00 journal usage of sledge::view <p>follow is an examle trigger code of Sledge::View.</p><blockquote><div><p> <tt>package Your::Pages::Base;<br>use strict;<br>use warnings;<br>use base qw/Sledge::Pages::Compat/;<br>use Switch;<br>use Jcode;<br>use Sledge::Plugin::PluginLoader;<br>__PACKAGE__-&gt;load_plugins(<br>&nbsp; qw/Stash View/<br>);<br> &nbsp; <br>__PACKAGE__-&gt;add_trigger(<br>&nbsp; &nbsp; AFTER_DISPATCH =&gt; sub {<br>&nbsp; &nbsp; &nbsp; &nbsp; my $self = shift;<br> &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; switch ($self-&gt;r-&gt;param('output')) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'csv' {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $self-&gt;view('Sledge::View::CSV')-&gt;process;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $self-&gt;response-&gt;body(Jcode-&gt;new($self-&gt;response-&gt;body, 'euc')-&gt;sjis);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $self-&gt;view('Template')-&gt;process;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; }<br>);<br> &nbsp; <br>1;</tt></p></div> </blockquote> tokuhirom 2006-11-04T15:12:25+00:00 journal Sledge::View 0.04 released <p>I released Sledge::View 0.04 released.</p><p>This distribution includes the Sledge::View::CSV.</p><p>yeah, Japanese sales person often requires the CSV formatted files<nobr> <wbr></nobr>;-)</p><p>usage:</p><blockquote><div><p> <tt>package Your::Pages::Admin::Report;<br>use strict;<br>use warnings;<br>use base qw/Sledge::Pages::Compat/;<br>use Sledge::Plugin::View;<br>use Sledge::Plugin::Stash;<br> &nbsp; <br>__PACKAGE__-&gt;add_trigger(<br>&nbsp; AFTER_DISPATCH =&gt; sub {<br>&nbsp; &nbsp; my $self = shift;<br>&nbsp; &nbsp; if ($self-&gt;r-&gt;param('output') eq 'csv') {<br>&nbsp; &nbsp; &nbsp; &nbsp; $self-&gt;view('CSV')-&gt;process;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; else {<br>&nbsp; &nbsp; &nbsp; &nbsp; $self-&gt;view('Template')-&gt;process;<br>&nbsp; &nbsp; }<br>&nbsp; }<br>);<br> &nbsp; <br>sub dispatch_report {<br>&nbsp; &nbsp;my $self = shift;<br>&nbsp; &nbsp;$self-&gt;stash-&gt;{row} = [[qw/a b/], [qw/c d/]];<br>}</tt></p></div> </blockquote><p>and, your template is:</p><blockquote><div><p> <tt>&lt;table&gt;<br>&nbsp; [% FOR row IN rows %]<br>&nbsp; &lt;tr&gt;<br>&nbsp; &nbsp; [% FOR col IN row %]<br>&nbsp; &nbsp; &lt;td&gt;[% col %]&lt;/td&gt;<br>&nbsp; &nbsp; [% END %]<br>&nbsp; &lt;/tr&gt;<br>&nbsp; [% END %]<br>&lt;/table&gt;</tt></p></div> </blockquote><p>if user access to '/admin/report/report' then get the html table report, and if access to '/admin/report/report?output=csv' then get the csv report.</p><p>yes, you can easy to change the view.</p> tokuhirom 2006-11-03T14:41:29+00:00 journal Sledge::Config to YAML::Load <p>Long time ago, Sledge's config is written in codes, likes old version of Catalyst.</p><p>I want to write the config in YAML.YAML is cool, that is human readable and writable.</p><p>current style of Sledge::Config<nobr> <wbr></nobr>:</p><blockquote><div><p> <tt>package Proj::Config;<br>use strict;<br>use warnings;<br>use base qw(Sledge::Config Class::Singleton);<br> &nbsp; <br>sub case_sensitive { 0 }<br> &nbsp; <br>sub _new_instance {<br>&nbsp; &nbsp; my $class = shift;<br>&nbsp; &nbsp; unless (defined $ENV{SLEDGE_CONFIG_NAME}) {<br>&nbsp; &nbsp; &nbsp; &nbsp; do '/etc/' or warn $!;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; $class-&gt;SUPER::new($ENV{SLEDGE_CONFIG_NAME});<br>}<br> &nbsp; <br>1;<br> &nbsp; <br>package Proj::Config::_common;<br>use strict;<br>use vars qw(%C);<br>*Config = \%C;<br> &nbsp; <br>$C{TMPL_PATH}&nbsp; &nbsp; &nbsp;= '/path/to/tmpl_dir';<br>$C{COOKIE_NAME}&nbsp; &nbsp;= 'sledge_sid';<br>$C{COOKIE_PATH}&nbsp; &nbsp;= '/';<br>$C{COOKIE_DOMAIN} = undef;<br> &nbsp; <br>1;<br> &nbsp; <br>package Proj::Config::_development;<br>use strict;<br>use vars qw(%C);<br>*Config = \%C;<br> &nbsp; <br>$C{DATASOURCE}&nbsp; &nbsp; = [ 'dbi:mysql:sledge','root', '' ];<br> &nbsp; <br>1;<br>package Proj::Config::_product;<br>use strict;<br>use vars qw(%C);<br>*Config = \%C;<br> &nbsp; <br>$C{DATASOURCE}&nbsp; &nbsp; = [ 'dbi:mysql:sledge;host=','root', '' ];<br> &nbsp; <br>1;</tt></p></div> </blockquote><p>If you use the Sledge::Config::YAML, written by precuredaisuki, you can write config by YAML.</p><blockquote><div><p> <tt>package Your::Config;<br>use basei qw(Sledge::Config::YAML Class::Singleton);<br> &nbsp; <br>sub _new_instance {<br> &nbsp; my $class = shift;<br> &nbsp; <br> &nbsp; $class-&gt;SUPER::new($ENV{SLEDGE_CONFIG_NAME}, $ENV{SLEDGE_CONFIG_FILE});<br>}<br> &nbsp; <br>1;</tt></p></div> </blockquote><p>and, your yaml is:</p><blockquote><div><p> <tt>common:<br>&nbsp; tmpl_path:<nobr> <wbr></nobr>/path/to/tmpl_dir<br>&nbsp; cookie_name: sledge_sid<br>&nbsp; cookie_path:<nobr> <wbr></nobr>/<br>&nbsp; cookie_domain: ~<br>product:<br>&nbsp; datasource:<br>&nbsp; &nbsp; - dbi:mysql:sledge;host=<br>&nbsp; &nbsp; - root<br>&nbsp; &nbsp; -<br>development:<br>&nbsp; datasource:<br>&nbsp; &nbsp; - dbi:mysql:sledge<br>&nbsp; &nbsp; - root<br>&nbsp; &nbsp; -</tt></p></div> </blockquote> tokuhirom 2006-11-02T05:22:10+00:00 journal Sledge::Plugin::URIFor <p>I wrote the Sledge::Plugin::URIFor.This module provides $self-&gt;uri_for() method</p><blockquote><div><p> <tt>$self-&gt;uri_for('Proj::Pages::Foo' =&gt; 'add', {id =&gt; 35});<br># =&gt;<nobr> <wbr></nobr>/foo/add?id=35</tt></p></div> </blockquote><p>I complete wrote the code with tests.</p><p>But, Ikebe-san will release Sledge::Engine, that maybe includes url generating/parsing rule.</p><p>I'm waiting...</p><blockquote><div><p> <tt>package Sledge::Plugin::URIFor;<br>use strict;<br>use warnings;<br>our $VERSION = 0.01;<br>use Carp;<br>use Sledge::Utils;<br>use URI;<br> &nbsp; <br>sub import {<br>&nbsp; &nbsp; my $pkg = caller(0);<br> &nbsp; <br>&nbsp; &nbsp; no strict 'refs';<br>&nbsp; &nbsp; *{"$pkg\::uri_for"} = sub {<br>&nbsp; &nbsp; &nbsp; &nbsp; my $self = shift;<br> &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; my @args = @_;<br> &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; my $dir = Sledge::Utils::class2prefix($self);<br>&nbsp; &nbsp; &nbsp; &nbsp; my $page&nbsp; &nbsp;= '';<br>&nbsp; &nbsp; &nbsp; &nbsp; my $query&nbsp; = {};<br> &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; for my $arg (@args) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (ref $arg eq 'HASH') {&nbsp; &nbsp; # query<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $query = $arg;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } elsif ($arg =~<nobr> <wbr></nobr>/^[A-Z]/) { # module name<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my $appclass = Sledge::Utils::class2appclass($self);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $arg = "${appclass}::Pages::$arg" unless $arg =~<nobr> <wbr></nobr>/^$appclass/;<br> &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $dir = Sledge::Utils::class2prefix($arg);<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } elsif ($arg =~<nobr> <wbr></nobr>/^[a-z]/) { # page name<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; next if $arg eq 'index';&nbsp; &nbsp;# through<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $page&nbsp; &nbsp;= $arg;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; die "invalid argument : $arg";<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br> &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; my $uri = URI-&gt;new($dir<nobr> <wbr></nobr>.($dir eq '/' ? '' : '/'). $page);<br>&nbsp; &nbsp; &nbsp; &nbsp; $uri-&gt;query_form($query);<br> &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; return $uri-&gt;as_string;<br>&nbsp; &nbsp; };<br>}<br> &nbsp; <br>1;</tt></p></div> </blockquote><p>and tests:</p><blockquote><div><p> <tt>use strict;<br>use warnings;<br>use Test::Base;<br> &nbsp; <br>plan tests =&gt; 1*blocks;<br> &nbsp; <br>filters(<br>&nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; input =&gt; [qw/yaml/],<br>&nbsp; &nbsp; }<br>);<br> &nbsp; <br>run {<br>&nbsp; &nbsp; my $block = shift;<br> &nbsp; <br>&nbsp; &nbsp; eval qq{<br>&nbsp; &nbsp; &nbsp; &nbsp; package @{[ $block-&gt;pages ]};<br>&nbsp; &nbsp; &nbsp; &nbsp; use Sledge::Plugin::URIFor;<br>&nbsp; &nbsp; &nbsp; &nbsp; sub new { bless {}, shift }<br>&nbsp; &nbsp; };<br>&nbsp; &nbsp; die $@ if $@;<br> &nbsp; <br>&nbsp; &nbsp; my $page = $block-&gt;pages-&gt;new;<br>&nbsp; &nbsp; is( $page-&gt;uri_for( @{ $block-&gt;input } ), $block-&gt;expected,<br>&nbsp; &nbsp; &nbsp; &nbsp; $block-&gt;name );<br>};<br> &nbsp; <br>__END__<br> &nbsp; <br>=== simple<br>--- pages: Proj::Pages<br>--- input<br>- foo: bar<br>--- expected:<nobr> <wbr></nobr>/?foo=bar<br> &nbsp; <br>=== deep<br>--- pages: Proj::Pages::Foo<br>--- input<br>- add<br>--- expected:<nobr> <wbr></nobr>/foo/add<br> &nbsp; <br>=== complex<br>--- pages: Proj::Pages::Foo::Bar<br>--- input<br>- Bar::Baz<br>- edit<br>- foo: bar<br>&nbsp; bar: baz<br>--- expected:<nobr> <wbr></nobr>/bar/baz/edit?bar=baz&amp;foo=bar<br> &nbsp; <br>=== complex2<br>--- pages: Proj::Pages::Foo::Bar::Baz<br>--- input<br>- Proj::Pages::Bar::Baz<br>- edit<br>- foo: bar<br>&nbsp; bar: baz<br>--- expected:<nobr> <wbr></nobr>/bar/baz/edit?bar=baz&amp;foo=bar</tt></p></div> </blockquote> tokuhirom 2006-11-01T12:26:54+00:00 journal Sledge::Plugin::CreateConfig <p>I wrote the Sledge::Plugin::CreateConfig for Sledge2.0.This module generates crete_config method automatically.</p><blockquote><div><p> <tt>package Sledge::Plugin::CreateConfig;<br>use strict;<br>use warnings;<br>our $VERSION = 0.01;<br>use Carp;<br>use Sledge::Utils;<br>use UNIVERSAL::require;<br> &nbsp; <br>sub import {<br>&nbsp; &nbsp; my $pkg = caller(0);<br> &nbsp; <br>&nbsp; &nbsp; my $config_class = Sledge::Utils::class2appclass($pkg);<br>&nbsp; &nbsp; $config_class<nobr> <wbr></nobr>.= '::Config';<br> &nbsp; <br>&nbsp; &nbsp; $config_class-&gt;use or die $@;<br> &nbsp; <br>&nbsp; &nbsp; no strict 'refs';<br>&nbsp; &nbsp; *{"$pkg\::create_config"} = sub {<br>&nbsp; &nbsp; &nbsp; &nbsp; my $self = shift;<br>&nbsp; &nbsp; &nbsp; &nbsp; return $config_class-&gt;instance;<br>&nbsp; &nbsp; };<br>}<br> &nbsp; <br>1;</tt></p></div> </blockquote><p>Old style Sledge code is likes follow:</p><blockquote><div><p> <tt>package Your::Pages;<br>use base qw/Sledge::Pages::Compat/;<br> &nbsp; <br>use Your::Config;<br>sub create_config {<br>&nbsp; Your::Config-&gt;instance;<br>}</tt></p></div> </blockquote><p>I think, this is very verobse code.I want to write less codes.</p><p>If you use this plugin, you'll get a happy:</p><blockquote><div><p> <tt>package Your::Pages;<br>use base qw/Sledge::Pages::Compat/;<br>use Sledge::Plugin::CreateConfig;</tt></p></div> </blockquote><p>Now, This module is uped on CPAN.</p> tokuhirom 2006-11-01T05:17:23+00:00 journal load map to Sledge 2.0 follow is a list of load map to Sledge 2.0(draft). <ul> <li>wrap the Apache::Request</li><li>write the Sledge::Engine</li><li><ul> <li>support mod_perl2</li><li>support fastcgi</li></ul></li><li>split Sledge::MobileGate, very thick wrapper, to many plugins</li><li>add Sledge::Plugin::MobileAgent</li><li>use Encode, internal char code change euc-jp to utf-8</li><li>add the Sledge::Plugin::FormValidator::Simple?</li></ul><p> and more...</p> tokuhirom 2006-11-01T00:12:04+00:00 journal Sledge's components(draft) follow is a list of Sledge's core components. <dl> <dt>Sledge::Pages</dt><dd>Controller</dd><dt>Sledge::Authorizer</dt><dd>authorization</dd><dt>Sledge::Session</dt><dd>session state(e.g. cookie)</dd><dt>Sledge::SessionManager</dt><dd>session storage(e.g. memcached, mysql)</dd><dt>Sledge::Template</dt><dd>template engine(e.g. TT2, HTML::Template)</dd><dt>Sledge::Config</dt><dd>config object</dd></dl><p> I want to restructure the Sledge's components.</p> tokuhirom 2006-11-01T00:07:57+00:00 journal my first entry I started the blogs in 'use Perl'.<br><br>By the day, I write the blog about Sledge, web application frame work written in Perl, on<br><br><br>miyagawa suggests 'Your blog should be write on use Perl;'.<br><br>Yes, I started the blogs on use Perl;.<br><br>Yeah, I'll write the some entries about Sledge. tokuhirom 2006-10-31T23:41:36+00:00 others