Created
November 26, 2010 01:37
-
-
Save aerith/716169 to your computer and use it in GitHub Desktop.
動作確認ほとんどしてない。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
package MyApp::Model; | |
use DBIx::Skinny connect_info => +{ | |
dsn => 'dbi:SQLite:db/memo.sqlite', | |
}; | |
1; | |
package MyApp::Model::Schema; | |
use DateTime; | |
use DateTime::Format::Strptime; | |
use DateTime::Format::MySQL; | |
use DBIx::Skinny::Schema; | |
my $timezone = 'Asia/Tokyo'; | |
install_table pages => schema { | |
pk 'id'; | |
columns qw/id name body created_at updated_at/; | |
trigger pre_insert => callback { | |
my ($class, $args) = @_; | |
$args->{created_at} = DateTime->now(time_zone => $timezone); | |
}; | |
trigger pre_update => callback { | |
my ($class, $args) = @_; | |
$args->{updated_at} = DateTime->now(time_zone => $timezone); | |
}; | |
install_utf8_columns qw/name body/; | |
install_inflate_rule '^.+_at$' => callback { | |
inflate { | |
my $value = shift; | |
my $strptime = DateTime::Format::Strptime->new( | |
pattern => '%Y-%m-%d %H:%M:%S', | |
timezone => $timezone, | |
); | |
my $datetime = $strptime->parse_datetime($value); | |
DateTime->from_object(object => $datetime); | |
}; | |
deflate { | |
my $value = shift; | |
DateTime::Format::MySQL->format_datetime($value); | |
}; | |
}; | |
}; | |
1; | |
package MyApp::Model::Page::File; | |
use strict; | |
use warnings; | |
sub new { | |
my $class = shift; | |
my %data = @_; | |
bless \%data, $class; | |
} | |
sub name { $_[0]->{name} if exists $_[0]->{name} } | |
sub body { $_[0]->{body} if exists $_[0]->{body} } | |
1; | |
package MyApp::Module::List::File; | |
sub execute_get { | |
my $controller = shift; | |
my $pages = []; | |
my $format = 'data/*.txt'; | |
my @files = glob $format; | |
foreach (@files) { | |
m{.+/([^/\.]+)(?:\..*?)$}; | |
my $page = MyApp::Model::Page::File->new(name => $1, body => ''); | |
push @$pages, $page; | |
} | |
$controller->stash('pages', $pages); | |
$controller->render('index'); | |
} | |
1; | |
package MyApp::Module::List::Data; | |
sub execute_get { | |
my $controller = shift; | |
my $sql = qq/select * from pages where name <> 'index' order by created_at desc;/; | |
my @pages = MyApp::Model->search_by_sql($sql); | |
$controller->stash('pages', \@pages); | |
$controller->render('index'); | |
} | |
1; | |
package main; | |
use strict; | |
use warnings; | |
use utf8; | |
# for modules | |
if (exists $ENV{PERLBREW_PATH}) { | |
my @paths = split /:/, $ENV{PERLBREW_PATH}; | |
if (scalar @paths) { | |
use lib @paths; | |
} | |
} | |
use UNIVERSAL::require; | |
use UNIVERSAL::can; | |
use Mojolicious::Lite; | |
use Text::Markdown; | |
use Text::Textile; | |
use URI::Escape; | |
# 静的データの保存ディレクトリ | |
our $BASEPATH = 'data'; | |
# 編集用パスワード | |
our $PASSWORD = ''; | |
# セキュリティ用シークレットシード | |
app->secret(''); | |
app->helper(uri_escape_utf8 => sub { | |
shift; | |
URI::Escape::uri_escape_utf8($_[0]); | |
}); | |
app->helper(markdown => sub { | |
shift; | |
Text::Markdown->new->markdown($_[0]); | |
}); | |
app->helper(textile => sub { | |
shift; | |
Text::Textile->new->process($_[0]); | |
}); | |
get '/' => sub { | |
my $controller = shift; | |
my $page = MyApp::Model->single(pages => {name => 'index'}); | |
unless (defined $page) { | |
my @pages = MyApp::Model->search('pages'); | |
$controller->stash('pages', \@pages); | |
return $controller->render('index'); | |
} | |
$controller->stash('page', $page); | |
$controller->render('page'); | |
}; | |
get '/:name' => sub { | |
my $controller = shift; | |
my $name = $controller->param('name'); | |
my $page = (); | |
my $path = sprintf '%s/%s.txt', $BASEPATH, $name; | |
if ( -f $path && -r _ ) { | |
my $body = do { open my $fh, '<', $path; binmode $fh, ":encoding(utf8)"; local $/; <$fh> }; | |
$page = MyApp::Model::Page::File->new(name => $name, body => $body); | |
} else { | |
$page = MyApp::Model->single(pages => {name => $name}); | |
} | |
$controller->redirect_to(sprintf '/edit/%s', URI::Escape::uri_escape_utf8($name)) unless defined $page; | |
$controller->stash('page', $page); | |
$controller->render('page'); | |
}; | |
get '/edit/:name' => sub { | |
my $controller = shift; | |
my $name = $controller->param('name'); | |
unless (defined $name && length $name > 0) { | |
return $controller->render(template => 'error', status => 500, message => 'what page do you want to edit?'); | |
} | |
my $path = sprintf '%s/%s.txt', $BASEPATH, $name; | |
if ( -f $path && -r _ ) { | |
$controller->redirect_to(sprintf '/%s', URI::Escape::uri_escape_utf8($name)); | |
} | |
my $page = MyApp::Model->single(pages => {name => $name}); | |
$controller->stash('page', $page) if defined $page; | |
$controller->render('edit'); | |
}; | |
post '/update' => sub { | |
my $controller = shift; | |
my $password = $controller->param('password'); | |
unless (defined $password && length $password > 0) { | |
return $controller->render(template => 'error', status => 500, message => 'must input your password.'); | |
} | |
if (Digest::MD5::md5_hex($password) ne $PASSWORD) { | |
return $controller->render(template => 'error', status => 500, message => 'password you\'ve entered does not match'); | |
} | |
my $name = $controller->param('name'); | |
unless (defined $name && length $name > 0) { | |
return $controller->render(template => 'error', status => 500, message => 'what page do you want to edit?'); | |
} | |
my $page = MyApp::Model->single(pages => {name => $name}); | |
if (defined $page) { | |
MyApp::Model->update(pages => {body => $controller->param('body')} => {name => $name}); | |
} else { | |
MyApp::Model->insert(pages => { | |
name => $name, | |
body => $controller->param('body') | |
}); | |
} | |
$controller->redirect_to(sprintf '/%s', URI::Escape::uri_escape_utf8($name)); | |
}; | |
any '/(*path)' => sub { | |
my $controller = $_[0]; | |
my @path = split '/', $controller->param('path'); | |
unless (@path && scalar grep { /.+/ } @path > 1) { | |
return $controller->render(template => 'not_found', status => 404); | |
} | |
my $sub_name = join '::', map { ucfirst } @path; | |
my $module = sprintf 'MyApp::Module::%s', $sub_name; | |
my $method = sprintf 'execute_%s', lc $controller->req->method; | |
eval { | |
$module->use; | |
}; if ($@) { | |
# require YAML::Syck; return $controller->render(text => YAML::Syck::Dump([$@, $sub_name, $module, $method])); | |
return $controller->render(template => 'not_found', status => 404); | |
} | |
my $handler = $module->can($method); | |
unless (defined $handler && ref $handler) { | |
# require YAML::Syck; return $controller->render(text => YAML::Syck::Dump([$sub_name, $module, $method])); | |
return $controller->render(template => 'not_found', status => 404); | |
} | |
$handler->(@_); | |
}; | |
shagadelic; | |
__DATA__ | |
@@ favicon.ico | |
- | |
@@ stylesheets/memo.css | |
#contents { | |
width: 800px; | |
margin: 0 auto 200px auto; | |
} | |
#contents p { | |
font-size: 94%; | |
line-height: 1.8; | |
} | |
#contents pre.code { | |
overflow: scroll; | |
background: #f1f1f1; | |
border: 1px solid #cccccc; | |
margin: 1.2em; | |
padding: 1.5em; | |
} | |
#contents a.screenshot { | |
display: block; | |
text-align: center; | |
margin: 15px 0 10px 0; | |
} | |
#contents a.screenshot img { | |
width: 80%; | |
border: 1px solid #666666; | |
} | |
@@ layouts/contents.html.ep | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="UTF-8" /> | |
<title><%= $title %></title> | |
<link href="/stylesheets/memo.css" media="screen" rel="stylesheet" type="text/css" /> | |
<meta content="width=320, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport" /> | |
</head> | |
<body> | |
<div id="contents"> | |
<%= content %> | |
</div> | |
</body> | |
</html> | |
@@ index.html.ep | |
% layout 'contents', title => 'Page List'; | |
<h1>Page List</h1> | |
<ul> | |
<% foreach my $page (@$pages) { %> | |
<li><a href="/<%= uri_escape_utf8 $page->name =%>"><%= $page->name %></a></li> | |
<% } %> | |
</ul> | |
@@ page.html.ep | |
% layout 'contents', title => stash('name'); | |
<% if (ref stash('page')) { %> | |
<%= b(textile stash('page')->body)->encode('utf-8') =%> | |
<% } %> | |
@@ edit.html.ep | |
% layout 'contents', title => stash('title'); | |
<h1><%= stash('name') %> の編集</h1> | |
<form method="post" action="/update"> | |
<input type="hidden" id="name" name="name" value="<%= stash('name') %>"> | |
<div><textarea id="body" name="body" cols="80" rows="30"><% if (ref stash('page')) { %><%= stash('page')->body %><% } %></textarea></div> | |
<div><input type="password" id="password" name="password" /></div> | |
<div><input type="submit" value="Save" ></div> | |
</form> | |
@@ error.html.ep | |
% layout 'contents', title => 'Error'; | |
<% if (defined $message && length $message > 0) { %> | |
<p><%= $message %></p> | |
<% } else { %> | |
<p>Error</p> | |
<% } %> | |
@@ not_found.html.ep | |
% layout 'contents', title => 'Not Found'; | |
<p>Not Found</p> | |
@@ exception.html.ep | |
% layout 'contents', title => 'Internal Server Error'; | |
<p>Internal Server Error</p> | |
@@ db/install.sql | |
create table pages ( | |
id integer primary key not null, | |
name varchar(255) not null, | |
body text, | |
created_at datetime, | |
updated_at datetime | |
); | |
create index name_idx_1 ON pages (name); | |
@@ script/start.sh | |
#!/bin/bash | |
BASEPATH=./ | |
STARMAN=`which starman` | |
PIDFILE=${BASEPATH}/tmp/memo.pid | |
APPFILE=${BASEPATH}/app.psgi | |
APPHOST=127.0.0.1 | |
APPPORT=5050 | |
exec 2>&1 | |
cd $BASEPATH || exit 1 | |
case $1 in | |
start) | |
COMMAND="${STARMAN} -MFindBin --daemonize --host ${APPHOST} --port ${APPPORT} --pid ${PIDFILE} --app ${APPFILE}" | |
if [[ -x $STARMAN ]]; then | |
echo "Server started. You can reload or stop with this script." | |
`$COMMAND` | |
else | |
echo "Server could not be started." | |
exit 1; | |
fi | |
;; | |
stop) | |
if [[ -s $PIDFILE ]]; then | |
PID=`cat $PIDFILE` | |
kill -9 $PID; | |
rm -f $PIDFILE; | |
exit 0; | |
fi | |
exit 1; | |
;; | |
reload) | |
if [[ -s $PIDFILE ]]; then | |
PID=`cat $PIDFILE` | |
echo "command: kill -HUP ${PID}" | |
kill -HUP $PID; | |
exit 0; | |
fi | |
exit 1; | |
;; | |
*) | |
echo "Usage: server.sh {start|stop|reload}" | |
exit 0; | |
;; | |
esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment