君ならどう書く?(Sledgeを使って作ってみました。)というエントリーを書いたらmiyagawaさんからコメントが!「ソース!」ということなので、ソースを公開してみます。確かにソース公開しなきゃ何の意味もないですもんね(苦笑)
今回はsledge-setupで生成されるLLW::Pages、LLW::Config、LLW::Config::_common以外に、ロジック部分のLLW::Pages::Index、カレンダーを表すLLW::Calendar、スケジュールを表すLLW::Scheduleという3つのクラスを作りました。テンプレートはindex.html一枚で、トリガ用CGIはスケジュール表示、登録用のindex.cgiと削除用のdelete.cgiを作成しました。入力データのバリデーションは時間の都合上やってません(笑)それぞれのソースは以下の通りです。
LLW::Pages::Index
Pagesクラスを継承した今回の核となるクラスです。
package LLW::Pages::Index;
use strict;
use base qw/LLW::Pages/;
__PACKAGE__->tmpl_dirname('llw');
use LLW::Calendar;
use LLW::Schedule;
use Date::Simple;
# カレンダー、スケジュールの表示
sub dispatch_index {
my $self = shift;
my $year = int $self->r->param('year');
my $month = int $self->r->param('month');
my $day = int $self->r->param('day');
my $calendar = LLW::Calendar->new($year, $month) || LLW::Calendar->new;
my $date = Date::Simple->new($year, $month, $day) || Date::Simple->new;
my $schedules = LLW::Schedule->search(schedule_date=>$date,
{order_by=>'schedule_timestamp'} );
$self->tmpl->param( date=>$date, calendar => $calendar ,schedules => $schedules );
}
# スケジュールの登録
sub post_dispatch_index {
my $self = shift;
my $year = int $self->r->param('year');
my $month = int $self->r->param('month');
my $day = int $self->r->param('day');
my $title = $self->r->param('title');
my $content = $self->r->param('content');
my $date = Date::Simple->new($year,$month,$day);
eval {
my $schedule = LLW::Schedule->create({
schedule_title => $title,
schedule_content => $content,
schedule_date => $date
});
};
$self->tmpl->param(create_error=>1) if $@;
my $uri = sprintf 'index.cgi?year=%d&month=%d&day=%d', $year, $month, $day;
$self->redirect($uri);
}
# スケジュールの削除
sub dispatch_delete {
my $self = shift;
my $schedule = LLW::Schedule->retrieve(int $self->r->param('id'));
$schedule->delete if $schedule;
my $year = int $self->r->param('year');
my $month = int $self->r->param('month');
my $day = int $self->r->param('day');
my $uri = sprintf 'index.cgi?year=%d&month=%d&day=%d', $year, $month, $day;
$self->redirect($uri);
}
1;
LLW::Calendar
カレンダーを表すクラスです。拙作のDate::Simple::Monthというモジュールのサブクラスとして定義しています。Date::Japanese::Holidayをuseすることで、各日にちでis_holidayメソッドを利用可能にしています。
package LLW::Calendar;
use strict;
use base qw/Date::Simple::Month/;
use Date::Japanese::Holiday;
1;
LLW::Schedule
スケジュールを表したクラスです。Class::DBIのサブクラスになっています。今回はスケジュールを保存するためにmysqlを使いましたので、保存用のテーブルのスキーマも書いておきました。
package LLW::Schedule;
use strict;
use base qw/Class::DBI/;
use LLW::Config;
my $config = LLW::Config->instance();
__PACKAGE__->set_db('Main', @{$config->datasource}, {RaiseError=>1});
__PACKAGE__->columns(Primary=>'schedule_id');
__PACKAGE__->columns(Essential=>qw(schedule_date schedule_title schedule_content));
__PACKAGE__->columns(OTHERS=>qw(schedule_timestamp));
__PACKAGE__->has_a(schedule_date=>'Date::Simple');
1;
__END__
CREATE TABLE schedule (
schedule_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
schedule_date DATE NOT NULL,
schedule_title TEXT NOT NULL,
schedule_content TEXT,
schedule_timestamp TIMESTAMP
);
index.html
テンプレートです。実はここに一番時間をかけていたりします(笑)
<html>
<head>
<title>llw scheduler</title>
<meta http-equiv="Content-Type" content="text/html; charset=euc-jp">
<style type="text/css">
<!--
.weekday { color: #999999; }
.holiday { color: red; }
.today {background-color: yellow;}
.content { color: #999999; }
-->
</style>
</head>
<body>
<div id="calendar">
<table border="1" cellpadding="1" cellspacing="0">
<caption>[% calendar.year %]年[% calendar.month %]月</caption>
<tr>
<th>日</th>
<th>月</th>
<th>火</th>
<th>水</th>
<th>木</th>
<th>金</th>
<th>土</th>
</tr>
[% FOREACH d = calendar.wraparound_dates %]
[% IF loop.count % 7 == 1 %]<tr>[% END %]
<td>
[% IF d.month == calendar.month %]
<a class="[% IF d.is_holiday %]holiday[% ELSIF d == today %]today[% ELSE %]weekday[% END %]"
href="index.cgi?year=[% d.year %]&month=[% d.month %]&day=[% d.day %]">[% d.day %]</a>
[% ELSE %] [% END %]
</td>
[% IF loop.count % 7 == 0 %]</tr>[% END %]
[% END %]
</table>
<a href="index.cgi?year=[% calendar.prev_month.year %]&month=[% calendar.prev_month.month %]&day=[% date.day %]">前月</a>
<a href="index.cgi">今月</a>
<a href="index.cgi?year=[% calendar.next_month.year %]&month=[% calendar.next_month.month %]&day=[% date.day %]">来月</a>
</div>
<h3>[% date.year %]年[% date.month %]月[% date.day %]日の予定</h3>
<form action="index.cgi" method="post" name="" id="register_form">
タイトル<br>
<input name="title" type="text" id="title">
<br>
内容
<br>
<textarea name="content" id="content"></textarea>
<br>
<input type="submit" value="予定を追加">
<input name="year" type="hidden" id="year" value="[% date.year %]">
<input name="month" type="hidden" id="month" value="[% date.month %]">
<input name="day" type="hidden" id="day" value="[% date.day %]">
</form>
[% IF create_error %]データの登録に失敗しました。<br>[% END %]
<div id="schedule">
[% WHILE (s=schedules.next) %]
<div class="title">・[% s.schedule_title|html %] [<a href="delete.cgi?id=[% s.id %]&year=[% date.year %]&month=[% date.month %]&day=[% date.day %]">削除</a>]</div>
<div class="content">[% s.schedule_content|html|html_line_break %]</div>
[% END %]
</div>
</body>
</html>
index.cgi、delete.cgi
トリガ用CGIです
#! /usr/local/bin/perl
use strict;
use LLW::Pages::Index;
LLW::Pages::Index->new->dispatch('index');
#! /usr/local/bin/perl
use strict;
use LLW::Pages::Index;
LLW::Pages::Index->new->dispatch('delete');