Update
Thanks to an anonymous user, I was able to correct the error in my answer. return in the catch did not have the desired effect, since it was returned only from the catch routine.
If there was no exception, try returns the value of the try block; otherwise, the value of the catch . Thus, this version correctly executes and returns the value $c->redirect("/index") if insert succeeds, otherwise it calls and returns the value $c->show_error($_) .
sub insert_exec { my ($self, $c, $args) = @_; my ($params, $table, $model) = $self->_init({context => $c, args => $args}); try { $model->insert($table, $params); $c->redirect("/index"); } catch { $c->show_error($_); }; }
Try::Tiny is pretty much necessary, since error handling with eval very difficult to get right in the general case. The module documentation says this
This module contains simple try / catch / finally commands that are designed to minimize common errors with eval and NOTHING else blocks.
The focus of this module is on simple and reliable error handling for those who still want to write the correct eval blocks without 5 lines of a template each time.
Your code will look like this:
use Try::Tiny; sub insert_exec { my ($self, $c, $args) = @_; my ($params, $table, $model) = $self->_init({context => $c, args => $args}); try { $model->insert($table, $params); } catch { return $c->show_error($_); }; $c->redirect("/index"); }
which, I hope you agree, is much nicer.
Two points are noticeable:
try and catch are routines encoded as language words. This means that the semicolon after the final closing parenthesis is important.
For the same reason, return in try or catch blocks will not work as expected, and will simply exit the block, returning to the parent routine. See My update above.
In the catch $@ has its original value before try . The value resulting from the error is in $_