[Catalyst] Exceptions and templates and stuff.
Caroline Johnston
johnston at biochemistry.ucl.ac.uk
Wed Nov 30 21:05:00 CET 2005
Hi,
I've been playing with having my own error templates rather than the
default ones. I've got it set up so that I can throw exceptions I've
defined which know about their own templates. It seems to work, but I've
never used Exception::Class before and I've not entirely got the hang of
Catalyst yet, so can someone have a look and tell me if I'm doing
something really daft?
Cheers,
Cass.
----
1. In MyApp::end
if (my $e = ${$c->error}[-1]){
unless ($e->isa('MyApp::Exception')){
$e = new MyApp::Exception($c, "$e");
}
$c->stash->{template} = $e->template;
$c->stash->{err} = $e;
}
$c->error(0);
$c->forward('MyApp::V::TT') unless $c->res->output;
2. In a controller somewhere:
throw WebR::Exception($c, "I'm an unhelpful error message");
or,
throw WebR::Exception::DFV($c) unless $c->form->success();
3. My base Exception class is just an extension of Exception::Class::Base:
package MyApp::Exception;
use Exception::Class;
use base qw/Exception::Class::Base Class::Accessor::Fast
Class::Data::Inheritable/;
use Clone qw(clone);
use Data::Dumper;
use HTML::Entities;
__PACKAGE__->mk_classdata('template' );
__PACKAGE__->mk_classdata('debug_template');
__PACKAGE__->mk_accessors(qw/c res req stash/);
#set default templates
__PACKAGE__->template('error/error_basic.tt');
__PACKAGE__->debug_template('error/error_debug.tt');
#grab your context
sub _initialize{
my $self = shift;
$self->c(shift);
die "can't raise a MyApp::Exception without a catalyst context."
unless $self->c->isa('Catalyst::Base');
$self->SUPER::_initialize(@_);
}
#additional methods for debug template (mostly nicked from
finalize_errors)
sub req {
my $self = shift;
my $req = clone($self->c->req);
delete $req->{_context};
delete $req->{_body};
local $Data::Dumper::Terse = 1;
return encode_entities(Dumper($req));
}
sub res {
my $self = shift;
my $res = clone($self->c->res);
delete $res->{_context};
delete $res->{_finalized_headers};
local $Data::Dumper::Terse = 1;
return encode_entities(Dumper($res));
}
sub stash {
my $self = shift;
my $stash = $self->c->stash;
local $Data::Dumper::Terse = 1;
return encode_entities(Dumper($stash));
}
1;
and MyApp::Exception::DFV just changes the template:
package MyApp::Exception::DFV;
use base qw/MyApp::Exception/;
__PACKAGE__->template('error/dfv_error.tt');
1;
And then in my templates:
#error/error.tt
[%INCLUDE error/error_basic.tt%]
[%IF c.debug %]
[%INCLUDE error/error_debug.tt%]
[%END%]
error_basic.tt
<h1>Error!</h1>
[%IF err.message%]
<p class="warning"> [%err.message%] </p>
[%END%]
error_debug.tt (assuming css and js for the dropdown)
<h3>Response <a href="#" onclick="return dropdown('res');"> +/- </a></h3>
<pre id='res'>[% err.res %]</pre>
<h3>Request<a href="#" onclick="return dropdown('req');"> +/- </a></h3>
<pre id='req'>[% err.req %]</pre>
<h3>Stash<a href="#" onclick="return dropdown('stash');"> +/- </a></h3>
<pre id='stash'>[% err.stash %]</pre>
error_dfv.tt
<h3 class="warning">There was a problem with your form:</h3>
[% FOREACH thing IN c.form.msgs %]
<b class="warning">[% thing.key %]:</b> [% thing.value %] <br/>
[% END %]
<p/>
More information about the Catalyst
mailing list