Version 1.02
[catagits/Catalyst-Action-REST.git] / lib / Catalyst / Action / Serialize.pm
index 2c23151..73855b3 100644 (file)
@@ -7,6 +7,15 @@ extends 'Catalyst::Action::SerializeBase';
 use Module::Pluggable::Object;
 use MRO::Compat;
 
+our $VERSION = '1.02';
+$VERSION = eval $VERSION;
+
+has _encoders => (
+   is => 'ro',
+   isa => 'HashRef',
+   default => sub { {} },
+);
+
 sub execute {
     my $self = shift;
     my ( $controller, $c ) = @_;
@@ -14,9 +23,9 @@ 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)$/;
 
     my ( $sclass, $sarg, $content_type ) =
       $self->_load_content_plugins( "Catalyst::Action::Serialize",
@@ -33,23 +42,28 @@ 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;
 }
 
+__PACKAGE__->meta->make_immutable;
+
 1;
 
 =head1 NAME
@@ -104,7 +118,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:
@@ -124,7 +138,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