X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Controller-DBIC-API.git;a=blobdiff_plain;f=lib%2FCatalyst%2FController%2FDBIC%2FAPI.pm;h=b595fb49ba6bb585c0abdbb5c9619683cd4e94f9;hp=537bec24b31087083e66a4ee5b315c4c89cfb62b;hb=07b00970f381c386ff40e4f13d5ab3c8bcf72c43;hpb=0b0bf9111127c9fdad1e456169ec4cdd15b160f9 diff --git a/lib/Catalyst/Controller/DBIC/API.pm b/lib/Catalyst/Controller/DBIC/API.pm index 537bec2..b595fb4 100644 --- a/lib/Catalyst/Controller/DBIC/API.pm +++ b/lib/Catalyst/Controller/DBIC/API.pm @@ -2,11 +2,11 @@ package Catalyst::Controller::DBIC::API; #ABSTRACT: Provides a DBIx::Class web service automagically use Moose; -BEGIN { extends 'Catalyst::Controller::ActionRole'; } +BEGIN { extends 'Catalyst::Controller'; } use CGI::Expand (); use DBIx::Class::ResultClass::HashRefInflator; -use JSON; +use JSON (); use Test::Deep::NoTest('eq_deeply'); use MooseX::Types::Moose(':all'); use Moose::Util; @@ -27,8 +27,9 @@ sub _build__json { } with 'Catalyst::Controller::DBIC::API::StoredResultSource', - 'Catalyst::Controller::DBIC::API::StaticArguments', - 'Catalyst::Controller::DBIC::API::RequestArguments' => { static => 1 }; + 'Catalyst::Controller::DBIC::API::StaticArguments'; + +with 'Catalyst::Controller::DBIC::API::RequestArguments' => { static => 1 }; __PACKAGE__->config(); @@ -41,7 +42,7 @@ __PACKAGE__->config(); __PACKAGE__->config ( action => { setup => { PathPart => 'artist', Chained => '/api/rpc/rpc_base' } }, # define parent chain action and partpath class => 'MyAppDB::Artist', - result_class => 'MyAppDB::ResultSet::Artist', + resultset_class => 'MyAppDB::ResultSet::Artist', create_requires => ['name', 'age'], create_allows => ['nickname'], update_allows => ['name', 'age', 'nickname'], @@ -80,8 +81,7 @@ sub begin :Private { my ($self, $c) = @_; - Catalyst::Controller::DBIC::API::Request->meta->apply($c->req) - unless Moose::Util::does_role($c->req, 'Catalyst::Controller::DBIC::API::Request'); + Moose::Util::ensure_all_roles($c->req, 'Catalyst::Controller::DBIC::API::Request'); } =method_protected setup @@ -190,16 +190,19 @@ sub deserialize :Chained('setup') :CaptureArgs(0) :PathPart('') :ActionClass('De =method_protected generate_rs -generate_rs is used by inflate_request to generate the resultset stored in the current request. It receives $c as its only argument. And by default it merely returns the resultset from the stored_result_source on the controller. Override this method if you need to manipulate the default implementation of getting the resultset from the controller. +generate_rs is used by inflate_request to get a resultset for the current +request. It receives $c as its only argument. +By default it returns a resultset of the controller's class. +Override this method if you need to manipulate the default implementation of +getting a resultset. =cut sub generate_rs { - #my ($self, $c) = @_; - my ($self) = @_; + my ($self, $c) = @_; - return $self->stored_result_source->resultset; + return $c->model($self->class || $c->stash->{class}); } =method_protected inflate_request @@ -814,12 +817,18 @@ sub insert_object_from_params my ($self, undef, $object, $params) = @_; my %rels; - while (my ($k, $v) = each %{ $params }) { - if (ref($v) && !(reftype($v) eq reftype(JSON::true))) { - $rels{$k} = $v; + while (my ($key, $value) = each %{ $params }) { + if (ref($value) && !(reftype($value) eq reftype(JSON::true))) { + $rels{$key} = $value; + } + # accessor = colname + elsif ($object->can($key)) { + $object->$key($value); } + # accessor != colname else { - $object->set_column($k => $v); + my $accessor = $object->result_source->column_info($key)->{accessor}; + $object->$accessor($value); } } @@ -867,34 +876,32 @@ sub end :Private { my ($self, $c) = @_; - # check for errors - my $default_status; + # don't change the http status code if already set elsewhere + unless ($c->res->status && $c->res->status != 200) { + if ($self->has_errors($c)) { + $c->res->status(400); + } + else { + $c->res->status(200); + } + } - # Check for errors caught elsewhere - if ( $c->res->status and $c->res->status != 200 ) { - $default_status = $c->res->status; - $c->stash->{$self->stash_key}->{success} = $self->use_json_boolean ? JSON::false : 'false'; - } elsif ($self->get_errors($c)) { - $c->stash->{$self->stash_key}->{messages} = $self->get_errors($c); - $c->stash->{$self->stash_key}->{success} = $self->use_json_boolean ? JSON::false : 'false'; - $default_status = 400; - } else { + if ($c->res->status == 200) { $c->stash->{$self->stash_key}->{success} = $self->use_json_boolean ? JSON::true : 'true'; - $default_status = 200; + if($self->return_object && $c->req->has_objects) { + my $returned_objects = []; + push(@$returned_objects, $self->each_object_inflate($c, $_)) for map { $_->[0] } $c->req->all_objects; + $c->stash->{$self->stash_key}->{$self->data_root} = scalar(@$returned_objects) > 1 ? $returned_objects : $returned_objects->[0]; + } } - - unless ($default_status == 200) - { + else { + $c->stash->{$self->stash_key}->{success} = $self->use_json_boolean ? JSON::false : 'false'; + $c->stash->{$self->stash_key}->{messages} = $self->get_errors($c) + if $self->has_errors($c); + # don't return data for error responses delete $c->stash->{$self->stash_key}->{$self->data_root}; } - elsif($self->return_object && $c->req->has_objects) - { - my $returned_objects = []; - push(@$returned_objects, $self->each_object_inflate($c, $_)) for map { $_->[0] } $c->req->all_objects; - $c->stash->{$self->stash_key}->{$self->data_root} = scalar(@$returned_objects) > 1 ? $returned_objects : $returned_objects->[0]; - } - $c->res->status( $default_status || 200 ); $c->forward('serialize'); } @@ -932,6 +939,8 @@ push_error stores an error message into the stash to be later retrieved by L{message}) { $error = $params->{message}; @@ -951,9 +960,24 @@ get_errors returns all of the errors stored in the stash sub get_errors { my ( $self, $c ) = @_; + die 'Catalyst app object missing' + unless defined $c; return $c->stash->{_dbic_crud_errors}; } +=method_protected has_errors + +returns returns true if errors are stored in the stash + +=cut + +sub has_errors { + my ( $self, $c ) = @_; + die 'Catalyst app object missing' + unless defined $c; + return exists $c->stash->{_dbic_crud_errors}; +} + =head1 DESCRIPTION Easily provide common API endpoints based on your L schema classes. Module provides both RPC and REST interfaces to base functionality. Uses L and L to serialise response and/or deserialise request.