Modular approach without anonymous subrefs
I'm converting a CGI::Application web app to Dancer and have always used a modular approach so am I missing something if I prefer to do it this way: package MyApp; use Dancer qw(:syntax); use Login; use Logout; use Register; post '/login' => \&Login::run; post '/logout' => \&Logout::run; get '/register' => \&Register::run; 1; package Register; use Dancer qw(:syntax); sub run { ..... } 1; package Login; use Dancer qw(:syntax); sub run { ..... } 1; ? gvim
On 23 September 2012 01:27, gvim <gvimrc@gmail.com> wrote:
I'm converting a CGI::Application web app to Dancer and have always used a modular approach so am I missing something if I prefer to do it this way:
I think this is a very nice technique. My Routes.pm is growing to
3000 lines and I think I will refactor it using this same technique you have suggested.
The only disadvantage I can think of, is if you have many routes, then that might slow down startup as each file has to be read from disk. Alex
On 09/24/2012 03:24 PM, Alex C wrote:
On 23 September 2012 01:27, gvim<gvimrc@gmail.com> wrote:
I'm converting a CGI::Application web app to Dancer and have always used a modular approach so am I missing something if I prefer to do it this way:
I think this is a very nice technique. My Routes.pm is growing to
3000 lines and I think I will refactor it using this same technique you have suggested.
The only disadvantage I can think of, is if you have many routes, then that might slow down startup as each file has to be read from disk.
Alex
IMHO that should be negligible on a decent system, especially as already read a lot of files (modules from Dancer and prerequisites). In most cases (code) maintenance costs are greater than costs for resources. Regards Racke -- LinuXia Systems => http://www.linuxia.de/ Expert Interchange Consulting and System Administration ICDEVGROUP => http://www.icdevgroup.org/ Interchange Development Team
Hi guys, I'm new to Dancer but this is the way that I've gone down too. I'll probably get scorned on the list since I'm not yet sure on best practices (and there are probably hooks to do what I want), but I've also wrapped the methods so I can do other things around *all* requests: Note that I'm doing this for an JSON API: # {{{ API Version 1 prefix '/some/url/v1'; get '/url1' => handle( &My::Module1::Method1 ); get '/url2' => handle( &My::Module2::Method2 ); ... get '/urlN' => handle( &My::ModuleN::MethodN ); # }}} sub Handle { my ( $handler ) = @_; set serializer => 'JSON'; my $result; return sub { my $user = ... if ( not $user ) { log_stuff(); client_error( "User not found or incorrect password", 401 ); } var user => $user; other_stuff(); $result = $handler->( @_ ); }; if ( $@ ) { status( 500 ); error( $@ ); return { Status => 'Error', ErrorMessage => 'Internal server error', }; } return $result; } # where client_error() is just a convenience method around send_error() and logging There's probably a better way at doing this but I couldn't find the rights hooks at the time where I needed them for each step while developing. This works for me so I'll be sticking with it for now. If somebody has a better solution I'd like to know for the next project (or v2) :) (Also, if you're wondering why the exception handler, I needed to customise the JSON response.) Alfie On Tue, Sep 25, 2012, at 12:03 AM, Stefan Hornburg (Racke) wrote:
On 09/24/2012 03:24 PM, Alex C wrote:
On 23 September 2012 01:27, gvim<gvimrc@gmail.com> wrote:
I'm converting a CGI::Application web app to Dancer and have always used a modular approach so am I missing something if I prefer to do it this way:
I think this is a very nice technique. My Routes.pm is growing to
3000 lines and I think I will refactor it using this same technique you have suggested.
The only disadvantage I can think of, is if you have many routes, then that might slow down startup as each file has to be read from disk.
Alex
IMHO that should be negligible on a decent system, especially as already read a lot of files (modules from Dancer and prerequisites).
In most cases (code) maintenance costs are greater than costs for resources.
Regards Racke
-- LinuXia Systems => http://www.linuxia.de/ Expert Interchange Consulting and System Administration ICDEVGROUP => http://www.icdevgroup.org/ Interchange Development Team
_______________________________________________ Dancer-users mailing list Dancer-users@perldancer.org http://www.backup-manager.org/cgi-bin/listinfo/dancer-users
-- Alfie John alfiej@opera.com
On Tue, Sep 25, 2012, at 09:09 AM, Sawyer X wrote:
On 09/25/2012 01:01 AM, Alfie John wrote:
probably get scorned on the list since I'm not yet sure on best practices (and there are probably hooks to do what I want),
That's not a good reason to be scorned, nor should or will you be. :)
Ha excellent :) Alfie -- Alfie John alfiej@opera.com
On Tue, Sep 25, 2012, at 09:01 AM, Alfie John wrote:
sub Handle { my ( $handler ) = @_;
set serializer => 'JSON';
my $result;
return sub { my $user = ...
if ( not $user ) { log_stuff(); client_error( "User not found or incorrect password", 401 ); }
var user => $user;
other_stuff();
$result = $handler->( @_ ); };
if ( $@ ) { status( 500 ); error( $@ );
return { Status => 'Error', ErrorMessage => 'Internal server error', }; }
return $result; }
Oops. Wrongly copied. What I've got is: if ( $@ ) { if ( ref( $@ ) and $@ =~ /Dancer/ ) { $@->rethrow(); } status( 500 ); error( $@ ); return { Status => 'Error', ErrorMessage => 'Internal server error', }; } The reasoning here is that if my convenience method client_error() gets called somewhere in the code, it will eventually call send_error(). This error handler then gets called which rethrows with the proper client error message given in client_erro() instead of the default 'Internal server error'. Alfie -- Alfie John alfiej@opera.com
On Mon, Sep 24, 2012 at 02:24:31PM +0100, Alex C wrote:
On 23 September 2012 01:27, gvim <gvimrc@gmail.com> wrote:
I'm converting a CGI::Application web app to Dancer and have always used a modular approach so am I missing something if I prefer to do it this way: I think this is a very nice technique. My Routes.pm is growing to 3000 lines and I think I will refactor it using this same technique you have suggested.
The one change I'd suggest is that instead of having things like this ... get '/register' => \&Register::run; do this: get '/register' => sub { # stuff to extract parameters from Dancer Register::run( named_param1 => ... named_param2 => ... ) } as this make it quite a bit easier to test your routes' code in isolation*. The ideal that I'm working towards (very slowly) at work is for those modules to have no Dancer-specific code in them at all. I'm still trying to figure out a nice way of coping with routes which can return failure (eg HTTP codes for "forbidden") without lots of code duplication in each route, but I've not thought that hard about it yet. Dancer is great at route creation and dispatch, session management etc - the web-specific bits of an app. But that's *all* it's good at (which is a good thing). I want to keep it the hell out of my application code! * I worship Christ the Unit Tester, which, with a bit of trickery, has a very rude abbreviation -- David Cantrell | Official London Perl Mongers Bad Influence What plaything can you offer me today?
participants (6)
-
Alex C -
Alfie John -
David Cantrell -
gvim -
Sawyer X -
Stefan Hornburg (Racke)