diff --git a/app.psgi b/app.psgi index a903b2c..914bd9e 100644 --- a/app.psgi +++ b/app.psgi @@ -1,13 +1,15 @@ #!perl +use lib 'lib'; use Plack::Builder; use Plack::App::Directory; use Plack::App::File; +use MakeYourOwnAdventure::Stories; builder { - mount "/static" => builder { - $app = Plack::App::Directory->new({ root => "static" })->to_app; - }; - mount "/" => builder { - $app = Plack::App::File->new(file => "static/index.html"); - } + mount "/static" => + Plack::App::Directory->new({ root => "static" })->to_app; + mount "/" => + Plack::App::File->new(file => "static/index.html")->to_app; + mount "/stories" => + MakeYourOwnAdventure::Stories->new()->to_app; }; diff --git a/design.txt b/design.txt index 7588f4e..1d5fe31 100644 --- a/design.txt +++ b/design.txt @@ -14,8 +14,8 @@ Story Page * Vote -APIs(democracy.local:5000): -* PUT /stories +APIs: +* POST /stories (Create a new story) ** title, story_so_far * GET /stories * GET /stories/:name diff --git a/lib/MakeYourOwnAdventure/Controller.pm b/lib/MakeYourOwnAdventure/Controller.pm new file mode 100644 index 0000000..b0007a9 --- /dev/null +++ b/lib/MakeYourOwnAdventure/Controller.pm @@ -0,0 +1,66 @@ +package MakeYourOwnAdventure::Controller; +use Moose::Role; +use TokyoCabinet; +use Guard; +use JSON qw/decode_json encode_json/; + +has 'db' => (is => 'ro', isa => 'Object', lazy_build => 1); + +sub _build_db { + my $self = shift; + my $db = TokyoCabinet::HDB->new; + return $db; +} + +sub read_db { + my $self = shift; + my $db = $self->db; + if(!$db->open("data/casket.tch", $db->OREADER | $db->OCREAT)){ + my $ecode = $db->ecode(); + printf STDERR ("open error: %s\n", $db->errmsg($ecode)); + } + return $db, guard { $db->close; $self->clear_db }; +} + +sub write_db { + my $self = shift; + my $db = $self->db; + if(!$db->open("data/casket.tch", $db->OWRITER | $db->OCREAT)){ + my $ecode = $db->ecode(); + die "open error: ".$db->errmsg($ecode); + } + return $db, guard { $db->close; $self->clear_db }; +} + +sub get_stories { + my $self = shift; + my ($db,$g) = $self->read_db; + $db->iterinit(); + my @stories; + while (defined(my $key = $db->iternext())) { + my $value = $db->get($key); + next unless (defined($value)); + push @stories, json_decode($value); + } + return \@stories; +} + +sub get_story { + my ($self, $key) = @_; + my ($db,$g) = $self->read_db; + my $value = $db->get($key); + return unless defined($value); + return json_decode($value); +} + +sub put_story { + my ($self, $key, $hash) = @_; + my ($db,$g) = $self->write_db; + my $value = json_encode($hash); + unless ($db->put($key,$value)) { + my $ecode = $db->ecode(); + die "put error: ".$db->errmsg($ecode); + } +} + +1; diff --git a/lib/MakeYourOwnAdventure/Stories.pm b/lib/MakeYourOwnAdventure/Stories.pm new file mode 100644 index 0000000..b5da596 --- /dev/null +++ b/lib/MakeYourOwnAdventure/Stories.pm @@ -0,0 +1,43 @@ +package MakeYourOwnAdventure::Stories; +use Moose; +use JSON qw/decode_json encode_json/; +use Plack::Request; +use namespace::clean -except => 'meta'; + +with 'MakeYourOwnAdventure::Controller'; + +sub to_app { + my $self = shift; + + return sub { + my $env = shift; + my $req = Plack::Request->new($env); + + # GET or PUT? + if ($req->method eq 'GET') { + my $content = encode_json($self->get_stories); + return [200, ['Content-Type' => 'application/json'], [\$content]]; + } + elsif ($req->method eq 'POST') { + my $title = $req->param('title'); + my $story_so_far = $req->param('story_so_far'); + + unless ($title and $story_so_far) { + return [400, ['Content-Type' => 'text/plain'], ["Bad params"]]; + } + + (my $name = $title) =~ s/[^\w]+/_/g; + my $story = { + name => $name, + title => $title, + story => $story_so_far, + }; + $self->put_story($name, $story); + return [201, ['Location' => "/stories/$name", 'Content-Type' => 'application/json'], [encode_json($story)]]; + } + }; +} + + +__PACKAGE__->meta->make_immutable; +