I am reading the section of Mojolicious::Guides::Growing where it tells you how to grow a Mojolicious::Lite into a "well organized" cpan-uploadable application. First, it tells you to split the M::L app into a launch script and an application class.
package MyApp;
use Mojo::Base 'Mojolicious';
use MyUsers;
sub startup {
my $self = shift;
# ...auth stuff omitted...
my $r = $self->routes;
$r->any('/' => sub {
my $self = shift;
my $user = $self->param('user') || '';
my $pass = $self->param('pass') || '';
return $self->render unless $self->users->check($user, $pass);
$self->session(user => $user);
$self->flash(message => 'Thanks for logging in.');
$self->redirect_to('protected');
} => 'index');
$r->get('/protected' => sub {
my $self = shift;
return $self->redirect_to('index') unless $self->session('user');
});
$r->get('/logout' => sub {
my $self = shift;
$self->session(expires => 1);
$self->redirect_to('index');
});
}
1;
This makes sense to me. But then it goes on to say that this application class can further be refactored into a controller class with the actions, and the application class itself can be reduced to the routing information:
package MyApp::Login;
use Mojo::Base 'Mojolicious::Controller';
sub index {
my $self = shift;
my $user = $self->param('user') || '';
my $pass = $self->param('pass') || '';
return $self->render unless $self->users->check($user, $pass);
$self->session(user => $user);
$self->flash(message => 'Thanks for logging in.');
$self->redirect_to('protected');
}
sub protected {
my $self = shift;
return $self->redirect_to('index') unless $self->session('user');
}
sub logout {
my $self = shift;
$self->session(expires => 1);
$self->redirect_to('index');
}
1;
package MyApp;
use Mojo::Base 'Mojolicious';
use MyUsers;
sub startup {
my $self = shift;
# ...auth stuff omitted...
my $r = $self->routes;
$r->any('/')->to('login#index')->name('index');
$r->get('/protected')->to('login#protected')->name('protected');
$r->get('/logout')->to('login#logout')->name('logout');
}
1;
I don't see why this is superior to the "hybrid" version where routes and actions are intermingled, because now in order to redirect between the actions with redirect_to() in the controller, you need to look at the routing infomration in a different file, and if you want to change a url, you have to do it in two different files instead of one. This:
$r->get('/protected' => sub {
my $self = shift;
return $self->redirect_to('index') unless $self->session('user');
});
turns into:
sub protected {
my $self = shift;
return $self->redirect_to('index') unless $self->session('user');
}
$r->get('/protected')->to('login#protected')->name('protected');
Which has the word "protected" 4 times in two different files (although I'm not sure what the name("protected") does yet).
I'm a complete novice when it comes to web development, by the way.
It's not superior; rather, it's different.
As soon as you move beyond one developer, having your app in one file is no longer a benefit; you'll end up stepping on each others toes. Even if you're the only dev, it's never easy to keep track of locations in files of 1000+ lines. In addition, being able to look at one file and determine all your routes at a glance is quite useful when you have more than just a few routes, not to mention 100+.
Also, you don't have to change a redirect url in a controller action when the route changes. Mojolicious will do the work for you if you're making use of named routes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With