Skip to content

Instantly share code, notes, and snippets.

@mix3
Created April 23, 2011 17:09
Show Gist options
  • Save mix3/938782 to your computer and use it in GitHub Desktop.
Save mix3/938782 to your computer and use it in GitHub Desktop.
Mojolicious::Lite + Teng + SNBinder + Xslate (+ SQLite/OnMemory)でCRUDアプリ
package Message;
use parent 'Teng';
__PACKAGE__->load_plugin('Pager');
use Class::Method::Modifiers;
around delete => sub {
my ($orig, $self, $table_name, $delete_condition) = @_;
my $update_row_data = {
deleted_at => DateTime->now->set_time_zone('Asia/Tokyo'),
};
$self->update($table_name, $update_row_data, $delete_condition);
};
before insert => sub {
my ($self, $table_name, $row_data) = @_;
$row_data->{created_at} = DateTime->now->set_time_zone('Asia/Tokyo');
$row_data->{updated_at} = DateTime->now->set_time_zone('Asia/Tokyo');
};
before update => sub {
my ($self, $table_name, $update_row_data, $update_condition) = @_;
if (!$update_row_data->{deleted_at}) {
$update_row_data->{updated_at} = DateTime->now->set_time_zone('Asia/Tokyo');
}
};
1;
package Message::Schema;
use Teng::Schema::Declare;
use DateTime::Format::MySQL;
table {
name 'message',
pk 'id',
columns qw(
id
message
created_at
updated_at
deleted_at
);
deflate qr/_at$/ => sub {
DateTime::Format::MySQL->format_datetime(shift);
};
inflate qr/_at$/ => sub {
DateTime::Format::MySQL->parse_datetime(shift);
};
};
1;
package main;
use utf8;
use Mojolicious::Lite;
plugin 'xslate_renderer';
use Devel::KYTProf;
my $model = Message->new(
dbh => DBI->connect(
'dbi:SQLite:dbname=:memory:', '', '',
{
RaiseError => 1,
PrintError => 0,
AutoCommit => 1,
sqlite_unicode => 1,
}
)
);
$model->do(q{
CREATE TABLE IF NOT EXISTS message (
id INTEGER PRIMARY KEY AUTOINCREMENT,
message TEXT NOT NULL,
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL,
deleted_at DATETIME
)
});
get '/' => sub{
my $self = shift;
$self->render(
handler => 'tx',
);
} => 'index';
get '/edit/:id' => sub {
my $self = shift;
my $itr = $model->search_named(q{
SELECT * FROM message WHERE id = :id AND deleted_at IS NULL
}, {id => $self->param('id')});
my $result = $itr->next;
return $self->render(
handler => 'tx',
template => 'error',
message => '該当メッセージが見つからないか、既に削除されています'
) if !$result;
$self->render(
handler => 'tx',
id => $result->get_column('id'),
message => $result->get_column('message')
);
} => 'edit';
post '/create' => sub {
my $self = shift;
return $self->render(
handler => 'tx',
template => 'error',
message => 'メッセージを入力してください'
) if !$self->param('message');
$model->insert('message', {
message => $self->param('message'),
});
$self->redirect_to('index');
};
post '/update' => sub {
my $self = shift;
return $self->render(
handler => 'tx',
template => 'error',
message => 'メッセージを入力してください'
) if !$self->param('message');
$model->update('message',
{
message => $self->param('message'),
},
{
id => $self->param('id'),
}
);
$self->redirect_to('index');
};
get '/delete/:id' => sub {
my $self = shift;
$model->delete('message', {
id => $self->param('id'),
});
$self->redirect_to('index');
};
get '/show/:id' => sub {
my $self = shift;
my $itr = $model->search_named(q{
SELECT * FROM message WHERE id = :id AND deleted_at IS NULL
}, {id => $self->param('id')});
my $row = $itr->next;
my $result = !$row ? {} : $row->get_columns;
$self->render('json' => $result);
};
get '/list' => sub {
my $self = shift;
my $page = $self->param('page') || 1;
my ($rows, $pager) = $model->search_with_pager(
'message',
{
deleted_at => \'IS NULL',
},
{
order_by => 'id DESC',
page => $page,
rows => 3,
}
);
my $result = [];
foreach my $row (@$rows) {
push @$result, $row->get_columns;
}
$self->render('json' => $result);
};
app->start;
__DATA__
@@ base.tx
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script src="http://www.google.com/jsapi" type="text/javascript"></script>
<script type="text/javascript">//<![CDATA[
google.load('jquery', '1.4.4');
//]]></script>
<script src="https://github.com/snakajima/SNBinder/raw/master/snbinder-0.5.3.js" type="text/javascript"></script>
<title>Mojolicious::Lite + Teng + SNBinder + Xslate (+ SQLite/OnMemory)</title>
</head>
<body>
: block content -> { }
</body>
</html>
@@ form.tx
<form method="post" action="<: $path :>">
: if ($id) {
<input type="hidden" name="id" value="<: $id :>">
: }
<p><textarea name="message" cols="50" rows="10" ><: $message :></textarea></p>
<p><input type="submit" /></p>
</form>
@@ index.html.tx
: cascade base
: override content -> {
<script type="text/javascript">//<![CDATA[
$(document).ready(function(){
var template = "<hr /><p>$(.message)</p><p>[<a href=\"/edit/$(.id)\">編集</a>][<a href=\"/delete/$(.id)\">削除</a>]</p>";
SNBinder.get('/list', null, true, function(json){
$('#list').html(SNBinder.bind_rowset(template, json));
});
});
//]]></script>
: include form { path => "/create" }
<div id="list" />
: }
@@ edit.html.tx
: cascade base
: override content -> {
: include form { path => "/update", message => $message }
: }
@@ error.html.tx
: cascade base
: override content -> {
ERROR: <: $message :>
: }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment