Mojoliciousが1.01になりましたね。
まあ、それとは関係ないですが、jQueryを使ってAJAXなチャットを作ってみたので晒してみようかと思います。
AJAX自体、やった事が無いので、もっと良いやり方があるとは思います。
値の受け渡しはJSONを使ったのですが、Mojolicious側の受け取り方法がよく分からなくて$self->req->jsonとか、Mojo::JSON->newとかやっていたのですが、結果的に普通に$self->paramで受け取れるのがわかって、凄いと思いました。
JavaScript側では、Perlからのtime値をどうやって渡すのかが、調べていてもよく分からなかったので、正解に行き着くのが大変でした。
ミリセカンドで渡す、というのは気づきませんでした。
常識すぎてあまり書かれないんでしょうか
。
#!/usr/bin/env perl
#utf8
# use Acme::PerlTidy;
use utf8;
package DataModel;
use base 'Data::Model';
use Data::Model::Schema;
use Data::Model::Driver::DBI;
my $dbfile = qq{$0.db};
my $dsn = qq{dbi:SQLite:dbname=$dbfile};
my $driver = Data::Model::Driver::DBI->new(
dsn => $dsn,
connect_options => {sqlite_unicode => 1},
);
base_driver($driver);
install_model messages => schema {
key 'id';
column id => int => {auto_increment => 1};
column msg => char => {required => 1};
column ts => char => {required => 1};
};
unless (-f $dbfile) {
my $dbh = DBI->connect($dsn, '', '', {RaiseError => 1, PrintError => 0})
or DBI->errstr;
for my $sql (__PACKAGE__->as_sqls) {
$dbh->do($sql) or die $dbh->errstr;
}
$dbh->disconnect;
}
package main;
use Mojolicious::Lite;
use Mojo::Util qw/md5_sum/;
app->secret(md5_sum $0 )->log->level('debug')->path(qq{$0.log})
->debug(app->secret);
app->helper(model => sub { my $dbh = DataModel->new });
get '/' => 'index';
get '/json' => sub {
my $self = shift;
my $model = $self->model;
my $messages = [
$model->get(
'messages' => {
where => [id => {'>' => $self->param('from_id')}],
order => [{id => 'ASC'}],
}
)
];
my @json;
for my $msg (@{$messages}) {
push @json,
{ id => $msg->id,
msg => $msg->msg,
ts => $msg->ts,
};
}
$self->render(json => [@json]);
} => 'json';
post '/json' => sub {
my $self = shift;
my $time = time;
my $model = $self->model;
$model->set(
'messages' => {
msg => $self->param('msg'), # jsonもparamで取れる
ts => $time,
}
);
};
app->start;
__DATA__
@@ index.html.ep
% layout 'main';
%= javascript begin
jQuery(function($) {
$("#message").focus();
var params = $.extend({
refresh:5,
timer:0,
latest:0
},params);
var add_log = function(text){
$('#for_ajax').prepend("<p>" + text + "</p>");
};
var format_date = function(d){
var yyyy = d.getFullYear();
var mm = '0' + (d.getMonth() + 1);
var dd = '0' + d.getDate();
var hh = '0' + d.getHours();
var nn = '0' + d.getMinutes();
var ss = '0' + d.getSeconds();
return yyyy
+ '/' + mm.slice(-2)
+ '/' + dd.slice(-2)
+ ' ' + hh.slice(-2)
+ ':' + nn.slice(-2)
+ ':' + ss.slice(-2);
};
var reload_json = function(){
$.getJSON(
"<%= url_for 'json' %>",
{ 'from_id':params.latest },
function(json) {
$.each(json, function(i, val){
params.latest = val.id;
var latest = new Date();
latest.setTime(val.ts * 1000);
add_log(val.id + ". " + val.msg + " <small>" + format_date(latest) + "</small>");
});
clearTimeout(params.timer);// 念のためタイマーをリセット
params.timer = setTimeout(reload_json,params.refresh*1000);// 次回の実行はparams.refresh秒後
}
);
};
params.timer = setTimeout(reload_json,0);// 一回目実行
$("#msg_form").submit(function() {
if ( 0 < $("#message").val().length ) {
$.post("<%= url_for 'json' %>", {
'msg':$("#message").val(),
},
function(json) {
}, 'json');
$("#message").val('');
}
return false;
})
});
% end
<div>
<%= form_for '/' => (method => 'post', id => 'msg_form') => begin %>
<%= text_field 'msg' => (id => 'message') %>
<%= submit_button '発言する' %>
<% end %>
</div>
<div id="for_ajax"></div>
@@ layouts/main.html.ep
<!DOCTYPE html>
<html>
<head>
<meta charset="<%= app->renderer->encoding %>">
<title>Mojolicious</title>
%= javascript 'https://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js'
</head>
<body><%= content %></body>
</html>

