-
Notifications
You must be signed in to change notification settings - Fork 0
Helpful Code Snippets
Mojolicious has an extremely powerful routing model. The following is a cut and paste example of using the Mojolicious bridge and waypoint route methods. The full documentation for Mojolicious routes can be found at http://mojolicio.us/perldoc/Mojolicious/Guides/Routing. To run this cookbook example, paste the following code into your mojolicious application startup subroutine. Assuming your Mojolicious application is listening on http://localhost:3000, enter the following URL's into your browser after restarting Mojolicious.
/foo
/foo/bar
/foo/baz
/foo/bam
/foo/bam/groovy
Place these in your startup subroutine
my $r = $self->routes;
my $foo = $r->bridge('/foo')->to(cb => sub {
my $self = shift;
$self->stash(foo => 'I am /foo!' );
});
$foo->route('/bar')->to(cb => sub {
my $self = shift;
$self->render(text => 'I am /bar! ' . $self->stash('foo') );
});
$foo->route('/baz')->to(cb => sub {
my $self = shift;
$self->render(text => 'I am /baz ' . $self->stash('foo') );
});
my $bam = $foo->waypoint('/bam')->to(cb => sub {
my $self = shift;
$self->render(text => 'I am /bam ' . $self->stash('foo') );
});
$bam->route('/:myvar')->to(cb => sub {
my $self = shift;
$self->render(text => 'I am /bam ' . $self->stash('foo') . $self->stash('myvar') );
});
These examples use the callback feature of Mojolicious routes however, you can also use controllers and actions to set variables and "do stuff". The sky is the limit. Use your imagination and have fun!
Additional information on Mojolicious routes can be found at:
http://mojolicio.us/perldoc/Mojolicious/Guides/Routing
https://github.com/kraih/mojo/wiki/Routes-for-non-lite-apps
after_static_dispatch => sub { return if $_[0]->stash->{'mojo.rendered'}; CODE }
This example has been more or less obsoleted since the existance of Mojolicious::Plugin::Authentication, which basically does all this for you, but I'll leave the example here if you want a DIY approach :)
This assumes you're using the Mojolicious::Plugin::Session plugin, backed by MojoX::Session
# place these two functions in a controller, assuming Auth.pm
sub check_session {
my $self = shift;
my $session = $self->stash->{'mojox-session'};
if($session->load) {
if($session->is_expired) {
$session->flush;
$session->create;
} else {
my $uid = $session->data('uid');
my $user;
if($uid && ($user = <load_your_user_here>)) {
$self->stash->{'user'} = $user;
$session->extend_expires;
$session->flush;
}
}
} else {
$session->create;
$session->flush;
}
}
sub check_loggedin {
my $self = shift;
return 1 if($self->stash('user'));
# either render a template, or redirect
$self->render(template => 'auth/login') and return 0;
#$self->redirect_to('/login') and return 0;
}
Then, in your main app file, you can do the following:
my $r = $self->routes->bridge('/')->to('auth#check_session');
my $routes_requiring_loggedin_user = $r->bridge('/')->to('auth#check_loggedin')
# login page/handler
$r->route('/auth/login')->to('auth#login');
# a profile page that needs ppl to be logged in
$routes_requiring_loggedin_user->route('/profile')->to('profile#index');
my $articles = $r->waypoint('/articles')->to('articles#list');
my $article = $articles->route('/:id')->to('#view');"
This hook gives you the possibility to mess with your data before rendering takes place. Imagine the following:
sub foo {
my $self = shift;
$self->stash(result => { ok => 1, message => 'Hi, I am Foo' });
}
Which is routed simply as: $r->route('/foo')->to('controller#foo');
Auto-rendering, a beautiful thing, will now merrily grab the template controller/foo.html.ep
if you request this as /foo or /foo.html. Imagine that you also want this URL to respond to JSON requests properly, but you don't want to manually do the if-then-else dance to determine how to call render. Well, if you don't, the renderer will try to render /controller/foo.json.ep
which isn't what you want.
Enter the before_render hook
$app->plugins->add_hook(before_render => sub {
my $self = shift;
my $controller = shift;
my $args = shift;
$controller->stash->{json} = delete($controller->stash->{result}) if($controller->stash->{format} eq 'json');
})
And now, your app will "do the right thing". The json stash key is automatically seen and will render json; if you request anything else, it will go look for the proper template.
Now imagine you have per-user defaults that you want to set in the stash, $app-
defaults> is nice for global (application wide) defaults, but per-user defaults are usually handled on a per-request basis; but here we go:
$app->plugins->add_hook(before_render => sub {
my $self = shift;
my $c = shift;
my $args = shift;
$c->stash->{user_colors} = $c->some_contrived_helper->get_user_colors;
});
Even more interesting things are most likely possible, but these two are the main reasons I'm pretty happy with the existance of this hook ;)