Fix generate_rs to set model to contents of stash->{class} if present and add tests.
[catagits/Catalyst-Controller-DBIC-API.git] / lib / Catalyst / Controller / DBIC / API.pm
index 99e11b7..b595fb4 100644 (file)
@@ -2,7 +2,7 @@ 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;
@@ -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');
 }