Fix docs citing incorrect method, "serialize_bad_request"
[catagits/Catalyst-Action-REST.git] / lib / Catalyst / Action / Serialize.pm
index cc1f838..057cc39 100644 (file)
@@ -7,8 +7,11 @@ extends 'Catalyst::Action::SerializeBase';
 use Module::Pluggable::Object;
 use MRO::Compat;
 
-our $VERSION = '0.81';
-$VERSION = eval $VERSION;
+has _encoders => (
+   is => 'ro',
+   isa => 'HashRef',
+   default => sub { {} },
+);
 
 sub execute {
     my $self = shift;
@@ -17,9 +20,20 @@ sub execute {
     $self->maybe::next::method(@_);
 
     return 1 if $c->req->method eq 'HEAD';
-    return 1 if length( $c->response->body );
+    return 1 if $c->response->has_body;
     return 1 if scalar @{ $c->error };
-    return 1 if $c->response->status =~ /^(?:204|3\d\d)$/;
+    return 1 if $c->response->status =~ /^(?:204)$/;
+    return 1 if defined $c->stash->{current_view};
+    return 1 if defined $c->stash->{current_view_instance};
+
+    # on 3xx responses, serialize if there's something to
+    # serialize, no-op if not
+    my $stash_key = (
+       $controller->{'serialize'} ?
+           $controller->{'serialize'}->{'stash_key'} :
+                $controller->{'stash_key'}
+           ) || 'rest';
+    return 1 if $c->response->status =~ /^(?:3\d\d)$/ && ! defined $c->stash->{$stash_key};
 
     my ( $sclass, $sarg, $content_type ) =
       $self->_load_content_plugins( "Catalyst::Action::Serialize",
@@ -36,18 +50,21 @@ sub execute {
     $c->log->debug(
         "Serializing with $sclass" . ( $sarg ? " [$sarg]" : '' ) ) if $c->debug;
 
+    $self->_encoders->{$sclass} ||= $sclass->new;
+    my $sobj = $self->_encoders->{$sclass};
+
     my $rc;
     eval {
         if ( defined($sarg) ) {
-            $rc = $sclass->execute( $controller, $c, $sarg );
+            $rc = $sobj->execute( $controller, $c, $sarg );
         } else {
-            $rc = $sclass->execute( $controller, $c );
+            $rc = $sobj->execute( $controller, $c );
         }
     };
     if ($@) {
-        return $self->_serialize_bad_request( $c, $content_type, $@ );
+        return $self->serialize_bad_request( $c, $content_type, $@ );
     } elsif (!$rc) {
-        return $self->_unsupported_media_type( $c, $content_type );
+        return $self->unsupported_media_type( $c, $content_type );
     }
 
     return 1;
@@ -55,6 +72,8 @@ sub execute {
 
 __PACKAGE__->meta->make_immutable;
 
+1;
+
 =head1 NAME
 
 Catalyst::Action::Serialize - Serialize Data in a Response
@@ -107,7 +126,7 @@ Takes a hashref, mapping Content-Types to a given serializer plugin.
 This is the 'fall-back' Content-Type if none of the requested or acceptable
 types is found in the L</map>. It must be an entry in the L</map>.
 
-=head2 stash_key 
+=head2 stash_key
 
 Specifies the key of the stash entry holding the data that is to be serialized.
 So if the value is "rest", we will serialize the data under:
@@ -127,7 +146,14 @@ perhaps for debugging.
 
 Daisuke Maki pointed out that early versions of this Action did not play
 well with others, or generally behave in a way that was very consistent
-with the rest of Catalyst. 
+with the rest of Catalyst.
+
+=head1 CUSTOM ERRORS
+
+For building custom error responses when serialization fails, you can create
+an ActionRole (and use L<Catalyst::Controller::ActionRole> to apply it to the
+C<end> action) which overrides C<unsupported_media_type> and/or C<serialize_bad_request>
+methods.
 
 =head1 SEE ALSO