Introduction
-
Mojolicious - "the Web in a Box!" - http://mojolicious.org
-
On CPAN: http://search.cpan.org/dist/Mojolicious/ .
-
A self-contained web-development framework that only depends on perl 5 and its core modules.
-
As a result: implements a lot of functionality that exists in many other CPAN distributions in slightly different ways.
-
Licence: Artistic 2.0 (open-source, mostly BSD-style).
Code Examples
# Using Mojolicious::Lite will enable "strict" and "warnings"
use Mojolicious::Lite;
# Route with placeholder
get '/:foo' => sub {
my $self = shift;
$self->render_text('Yea baby!');
};
# Start the Mojolicious command system
shagadelic;
More complex example, written by me for Insurgent Software and available on github under a yet undecided open-source licence:
#!/usr/bin/env perl
use strict;
use warnings;
use InsurgentSoftware::UserAuth::User;
use InsurgentSoftware::UserAuth::App;
use Mojolicious::Lite;
use MojoX::Session::Cookie;
use CGI qw();
use KiokuDB;
# Silence
app->log->level('error');
my $dir = KiokuDB->connect(
"dbi:SQLite:dbname=./insurgent-auth.sqlite",
create => 1,
columns =>
[
email =>
{
data_type => "varchar",
is_nullable => 1,
},
],
);
get '/' => sub {
my $self = shift;
return $self->render(
template => "index",
layout => 'insurgent',
title => "Main",
);
} => "index";
my $app = InsurgentSoftware::UserAuth::App->new(
{
dir => $dir,
}
);
my %actions_params =
(
'get' =>
[
['/register/', "register",],
['/login/' , "login",],
['/account' , "account_page",],
['/confirm-register' , "confirm_register",],
['/password-reset' , "password_reset",],
['/handle-password-reset' , "handle_password_reset",],
],
'post' =>
[
['/register-submit/', "register_submit",],
['/login-submit/' , "login_submit",],
['/account/change-info' , "change_user_info_submit",],
['/password-reset-submit' , "password_reset_submit",],
['/handle-password-reset-submit' , "handle_password_reset_submit",],
],
);
while (my ($verb, $actions) = each(%actions_params))
{
foreach my $action (@$actions)
{
my ($url, $action_name) = @$action;
__PACKAGE__->can($verb)->(
$url => sub {
my $controller = shift;
return $app->with_mojo($controller, $action_name);
} => $action_name
);
}
}
sub logout
{
my $self = shift;
delete($self->session->{'login'});
$self->render_text(
"<h1>You are now logged-out</h1>\n",
layout => 'insurgent',
title => "You are now logged-out",
);
return;
}
get '/logout' => (\&logout) => "logout";
shagadelic;
=head1 TODO
* Make sure that there are limits to the properties of a user (maximal length
of E-mail, password, etc.).
* Add a confirmation reminder feature to re-send the confirmation E-mail.
* Add a way to cancel a registration using the E-mail (in case it's an unwanted
registration.)
=cut
__DATA__
@@ index.html.ep
% layout 'insurgent';
<h1>Insurgent Software's User Management Application</h1>
<ul>
% if ($self->session->{'login'}) {
<li><a href="<%= url_for('account_page') %>">Go to Your Account</a></li>
% } else {
<li><a href="<%= url_for('login') %>">Login to an existing account</a></li>
<li><a href="<%= url_for('register') %>">Register a new account</a></li>
% }
</ul>
@@ register.html.ep
% layout 'insurgent';
<h1>Register an account</h1>
<%== $register_form %>
@@ login.html.ep
% layout 'insurgent';
<h1>Login form</h1>
<%== $login_form %>
@@ account.html.ep
% layout 'insurgent';
<h1>Account page for <%= $email %></h1>
<h2 id="change_info">Change User Information</h2>
<%== $change_user_info_form %>
@@ password_reset.html.ep
% layout 'insurgent';
<h1>Reset Your Password</h1>
<p>
The form below allows you to reset your password. Please enter the E-mail
with which you registered.
</p>
<%== $password_reset_form %>
@@ handle_password_reset.html.ep
% layout 'insurgent';
<h1>Reset Your Password</h1>
<p>
The form below allows you to reset your password. Please enter your new
password.
</p>
<%== $handle_password_reset_form %>
@@ layouts/insurgent.html.ep
<!doctype html><html>
<head>
<title><%= $title %> - Insurgent-Auth</title>
<link rel="stylesheet" href="/style.css" type="text/css" media="screen, projection" title="Normal" />
</head>
<body>
<div id="status">
<ul>
% if ($self->session->{'login'}) {
<li><b>Logged in as <%= $self->session->{'login'} %></b></li>
<li><a href="<%= url_for('account_page') %>">Account</a></li>
<li><a href="<%= url_for('logout') %>">Logout</a></li>
% } else {
<li><b>Not logged in.</b></li>
<li><a href="<%= url_for('login') %>/">Login</a></li>
<li><a href="<%= url_for('register') %>">Register</a></li>
% }
<li><a href="<%= url_for('password_reset') %>">Password Reset</a></li>
</ul>
</div>
<%== content %>
</body>
</html>
What I like about it
-
Easy to install (due to the lack of dependencies).
-
Mostly bug-free.
-
The code appears to be of good quality.
-
-
Results in brief, yet easy to understand code.
What I don’t like about it
-
Too many reinvented wheels to the ones on CPAN.
-
Possibly rounder but still different.
-
-
Slightly inconsistent API with many "Don’t-do-exactly-what-I-meanerism."
-
I found the documentation lacking, and often had to resort to reading or debugging the source.
-
"I just work here." - I got paid for doing a Mojolicious::Lite project and was instructed to use Mojolicious which I did.
-
I got paid to work with much worse technologies, though.
-
Verdict
-
The reinvented wheels is a deal breaker for me.
-
Mojolicious seems like a nice try, and I’m happy to get paid writing Mojolicious code, but it’s still not my pot at the end of the rainbow.
-
Some friends told me that Dancer is nice, and it relies on premade CPAN modules.
-
No first-hand experience with it.
-