So you have coded your newest web system in Mojolicious and would
like to test it in an environment where it "thinks" it's running on the
actual webserver, even though it's still running on your machine.
Add your www.example.com entry to point to 127.0.0.1 in /etc/hosts and
then redirect your localhost's port 80 to port 3000:
sudo iptables -t nat -I OUTPUT -p tcp -d 127.0.0.1 --dport 80 -j REDIRECT --to-ports 3000
No need to run as root!
In the previous installment,
we built a basic site with Zurb Foundation.
We were able to split the main HTML wrapper into a layout file, but our
index.html
that we passed to the render
function had to have the
whole rest of the row
and column
divisions. We really want to just
have our "content" consist only of the body of each page, and let the
template system take care of the row/column site structure and any
navigation or sidebars.
Doing this highlighted how different Mojolicious is from using
something like PHP, or even Ruby on Rails. In using, or trying to use
those, I spent more time getting frustrated at PHP's inconsistencies
(how many different kinds of 'equal' are there?) or ripping apart Rails
(there is One True way to speak to a database, and your existing schema
ain't it) and being frustrated at Ruby's zaniness (zero is true!) than
I did actually getting anything done.
Glen Hinkle (tempire) comments on this in a post to the Mojolicious
group
[groups.google.com, 11 November 2011]:
This is a matter of the tools built on top of the platform, rather
than the platform itself. Ruby's Rails distributes these sort of
tools and touts them as the hotness, but in practicality, they
don't provide much value…
Let's say you have a tool that creates your CRUD interface and
boilerplate. It looks great, because look at all the work it saved
you from doing! In reality, it's saved you nothing. When you customize
your app, you're going to have to re-organize and/or re- write
every piece of code/HTML. Guaranteed. These tools are a red herring
- they're simply not going to save you any time at all.
For example: You create a resource. Oh, but you need to verify
the data. Except, how you verify depends on the nature of your
data. That's ok, you can just take out the boilerplate and put
your own code in. Except, it ties in with the way it stores data
in the database. That's ok, you can replace that with your own
code. Except, that ties in with the way you've chosen to display
your data. That's ok, you can replace the templates with your own
code. Except, you need to show your templates in a specific way
so that it makes sense. That's ok, you can replace...
In the end, boilerplate templates limit you more than save you
time…
Attempt to create boilerplate on any platform, and you'll see how
useless it is after the 3rd web app, wherein maintaining the boilerplate
was more effort than creating the app itself. If it's not, you
don't actually want a custom web app, you want a CMS.
Once I realized that Mojo is just Perl inside, and all the idioms are
just old-fashioned syntactic sugar, everything started to become clear.
The very first thing we need to do to work in the "Foundation style" is
to build a hierarchy of nested sub-templates. Specifically, we want
rows and columns in a master template and then use the standard [content](http://mojolicio.us/perldoc/Mojolicious/Plugin/DefaultHelpers#content)
mechanism to drop text into the body.
With Mojolicious now, in an ep
(Encapsulated Perl)
file, you can specify:
% layout 'template_name'
and that layout can then say:
% extends 'subtemplate_name'
but be careful: the latter does not let you nest; the 'extending'
template's content is discarded. (Unless, that is, there has been no
content yet defined: an unlikely situation.)
So let's take the "Lite app" from Part I and add the lines shown in
bold here:
#!/usr/bin/env perl
use Mojolicious::Lite;
get '/' => sub {
my $c = shift;
$c->render('index',
msg => 'Welcome to the Mojolicious real-time web framework!');
};
app->start;
__DATA__
@@ index.html.ep
<strong>% layout 'site_design';</strong>
% title 'Welcome';
<div class="row">
<h2><%= $msg %></h2>
<div class="small-2 columns">2 columns</div>
<div class="small-10 columns">10 columns</div>
</div>
<div class="row">
<div class="small-3 columns">3 columns</div>
<div class="small-9 columns">9 columns</div>
</div>
<strong>@@ layouts/site_design.html.ep</strong>
<strong>% extends 'layouts/zurb';</strong>
<strong>This text does not appear.</strong>
@@ layouts/zurb.html.ep
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<!-- Zurb Foundation stuff -->
<meta name="viewport" content=
"width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/css/normalize.css">
<link rel="stylesheet" href="/css/foundation.min.css">
<script src="/js/vendor/modernizr.js"></script>
<!-- end Zurb -->
<title><%= title %></title>
</head>
<body>
<script src="/js/vendor/jquery.js"></script>
<script src="/js/foundation.min.js"></script>
<script>
$(document).foundation();
</script>
<%= content %>
</body>
</html>
Now the index HTML calls for the site_design template, which in turn
extends our Zurb Foundation template. The wrinkle is: In order to nest
templates, we must do this a bit differently.
As of Mojolicions 6.01, the built-in content helper functions
are:
content
stash
content_for
content_with
The first lets us define the content
stash (but, if that contains
anything at all, the function has no effect); the second function
returns the value of any stash including content; content_with replaces
the content (which we will use to wrap the content); and content_for
appends to the content
stash.
NOTE: An earlier version of this article led to the addition of
content_with in Mojolicious core. (See
[
this commit
](https://github.com/kraih/mojo/commit/275f0e75bf350d40542a67e5a9eaef84eaa08236)
.)
Let's take a bit of a sidetrack for a little understanding of what is
really going on. According to "Rendering" in the Mojolicious Guides,
The renderer is a tiny black box turning stash data into actual
responses utilizing multiple template systems and data encoding
modules.
Well that's all wonderful, but what does the black box do exactly? In
Mojolicious/Renderer.pm in your Perl installation, you can see the loop
in the render function, just below the comment:
`
sub render … # Extends
`
The extends loop there descends through the template definition,
which has the effect of rendering each of the include
, extends
, and
layout
calls. Again, do realize that in your template,
% layout 'site_design';
is a simple Perl function call, not some kind of magic. Understand too
that the layout's processing is deferred until after the remainder of
the containing template.
Back to the story. We write our index.html to declare what we want in
each of the containers: header, footer, sidebar, and then the content,
leaving the details of the rows and columns to our nested site layout
template, as follows (new parts in bold):
#!/usr/bin/env perl
use Mojolicious::Lite;
get '/' => sub {
my $c = shift;
$c->render('index',
msg => 'Welcome to the Mojolicious real-time web framework!');
};
app->helper(content_with => sub {
my ($c, $name, $content) = @_;
return unless defined $content;
my $hash = $c->stash->{'mojo.content'} ||= {};
return $hash->{$name} =
ref $content eq 'CODE' ? $content->() : $content;
});
app->start;
__DATA__
@@ index.html.ep
% layout 'site_design';
% title 'Welcome';
<strong>% content header => begin
<h2><%= $msg %></h2>
% end
% content footer => begin
<h5>Copyright ⓒ <%= ((localtime())[5]+1900) %></h5>
% end
% content sidebar => begin
<ul>
<li>Sidebar item 1</li>
<li>Sidebar item 2</li>
</ul>
% end
This plain text is the content − the body of the page.
</strong>
<strong>@@ layouts/site_design.html.ep
% extends 'layouts/zurb';
% content_with content => begin
<div class="row">
<div class="large-12 columns"><%= content 'header' %></div>
</div>
<div class="row">
<div class="small-3 columns"><%= content 'sidebar' %></div>
<div class="small-9 columns"><%= content %></div>
</div>
<div class="row">
<div class="large-12 columns"><%= content 'footer' %></div>
</div>
% end</strong>
@@ layouts/zurb.html.ep
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<!-- Zurb Foundation stuff -->
<meta name="viewport" content=
"width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/css/normalize.css">
<link rel="stylesheet" href="/css/foundation.min.css">
<script src="/js/vendor/modernizr.js"></script>
<!-- end Zurb -->
<title><%= title %></title>
</head>
<body>
<script src="/js/vendor/jquery.js"></script>
<script src="/js/foundation.min.js"></script>
<script>
$(document).foundation();
</script>
<%= content %>
</body>
</html>
Note the little trick for displaying the current year: We use the
list-returning version of localtime() but only want the year element
(the number of years since 1900) and print all four digits.:
<h5>Copyright ⓒ <%= ((localtime())[5]+1900) %></h5>
Thanks to everyone on #mojo
IRC, particularly jberger.
Next time, we will start adding database functionality. Meantime, have
fun with easy Foundation enabled Mojo sites!
From http://toroid.org/ams/etc/mojolicious-db-handles
we find this bit of code:
sub startup {
my $app = shift;
my ($user, $pass);
# read $user and $pass from config file
(ref $app)->attr(db => sub {
DBI->connect("dbi:Mysql:database=$db",
$user, $pass)
}
);
}
The concept is that Morbo, or Starman, or whatever PSGI server is
running your program, can use any kind of forking, but each instance of
your program will execute the startup code and create its own database
handle.
Some of the code is not too obvious:
ref $app
returns the class name of the main object. In my tests,
replacing this line with the more obvious: $app->attr(db =>…
worked just fine. EDIT: Apparently the ref
business is because he
wanted the class method, although because there isn't an instance
method by the same name of attr
, it doesn't matter.
The attr(...)
call is a Mojolicious method (see here)
that is described as, "Create attribute accessor for hash-based
objects." What that means is, the call actually creates a function
definition as a string, and then does an eval of the string,
thereby creating the named function (db
in this case) in the
given namespace (ref $app)
in this case.
And here's how you get the data back out:
$app->get('/test')->to(cb =>
sub{
my $self = shift;
$Data::Dumper::Indent = 1;
$self->render( 'text' => "TEST: ATTR of foo" . $self->app->foo .
"\n<pre>\n" . Dumper($self) . "</pre>" );
});
It's really a better idea to use DBIx::Connector
anyway, but the startup attribute trick might come in handy elsewhere.
One note on DBIX::Connector − Under the heading, Execution Methods we
see the code:
<span class="sh_variable">$conn</span><span class="sh_symbol">-></span><span class="sh_function">run</span><span class="sh_symbol">(</span><span class="sh_keyword">sub</span> <span class="sh_cbracket">{</span> <span class="sh_variable">$_</span><span class="sh_symbol">-></span><span class="sh_keyword">do</span><span class="sh_symbol">(</span><span class="sh_variable">$query</span><span class="sh_symbol">)</span> <span class="sh_cbracket">}</span><span class="sh_symbol">);</span>
It is not documented, but by reading the source (let's hear it for free
software!) what happens is that $_ is set, via the «local» keyword, to
temporarily be the database handle (dbh) of the connection within
execution of the code reference.
Thanks to mst and others on #perl for the
assistance.
A short tutorial.
Let's run through creating a Perl web application with Mojolicious
and styling by Zurb Foundation. We will
create this first as a full "application" and then as a "Lite" version.
Installing (Perlbrew and) Mojolicious
While perlbrew is not strictly required, the latest versions of Perl
have a number of features and optomizations that help Mojolicious.
There are two ways to install all this: Globally for all users (I
recommend this if you are administering the entire server, and want to
keep just one set of software) or in your home directory (best if you
share a server).
*Installing in your home directory *Following the instructions here
[perlbrew.pl], install Perlbrew into your home directory: something
like this:
\curl -L http://install.perlbrew.pl | bash
nice perlbrew -j 5 install perl-5.20.2
Note the 'nice' (to reduce impact on a running system) and the "-j
5" (to use up to five concurrent compilation threads) − although on
an active server, you might want to just use the default single
thread. Observe the final output of perlbrew: You will almost
certainly have to edit ~/.bash_profile
as it suggests, logout,
and then log back in to enable the perlbrew
command.
Now permanently switch to the new Perl, and install Mojolicious:
perlbrew switch perl-5.20.2
sudo sh -c "curl get.mojolicio.us | sh"
*Installing globally *Assuming a brand new machine (possibly a Linode
virtual machine), first we install the latest Mojolicious under
/local/bin ... if you don't do this as root this way, I recommend
you probably get a cpanminus version somewhere in your user home
directory.
sudo sh -c "curl get.mojolicio.us | sh"
Creating a Mojo "app"
OK now we can go into a working directory somewhere and type:
mojo generate app Test
which will create an entire tree of default files under the
subdirectory 'test' for a program called 'Test.'
At this point you should be able to start your example program:
cd Test
morbo script/test
and view the default text at http://localhost:3000
Adding Zurb Foundation to your "app"
Next we get the latest Foundation distribution from their website.
At the time of writing, this gave me foundation-5.3.1.zip. Create a
subdirectory called foundation
under the public directory and unzip
into there. This will create subdirectories css
and js
among a few
others.
wget <em>latest_foundation_link_from_above
</em>cd public
mkdir foundation
cd foundation
unzip ../../foundation*.zip
cd .. <em># back to Mojo project's public</em>
We are going to leave those files in a pristine tree so we can replace
them later, and create symbolics links to them. Note the slightly
curious use of relative paths in the symbolic links below. The multiple
../
are needed because symlinks are relative to the destination file,
not the directory where our shell happens to be when they are created.
Also, if only the destination directory and not a filename is given,
the destination filename is copied from the source (linked-to) file.
# Assuming the latest Foundation framework code
# is downloaded into the 'foundation' directory,
# and that we are currently in the 'public'
# directory in your generated mojo application,
# here we make symlinks from our document root
# into there, only for the files we actually use.
mkdir css
mkdir -p js/vendor
ln -s ../foundation/css/normalize.css css/
ln -s ../foundation/css/foundation.min.css css/
ln -s ../foundation/js/foundation.min.js js/
ln -s ../../foundation/js/vendor/jquery.js js/vendor/
ln -s ../../foundation/js/vendor/modernizr.js js/vendor/
It is worth a reminder that the syntax here is:
<tt>ln -s</tt> <em><small>{source (real file)} {destination (new link name)}</small></em>
Building the HTML for Foundation
Starting with the basic HTML from here:
http://foundation.zurb.com/docs/css.html
We copy some of the code from the original default.html.ep and create
the new templates/layouts/zurbish.html.ep as follows:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<!-- Zurb Foundation stuff -->
<meta name="viewport" content=
"width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/foundation.min.css">
<script src="js/vendor/modernizr.js"></script>
<!-- end Zurb -->
<title><%= title %></title>
</head>
<body>
<script src="js/vendor/jquery.js"></script>
<script src="js/foundation.min.js"></script>
<script>
$(document).foundation();
</script>
<%= content %>
</body>
</html>
Then in templates/example/welcome.html.ep we change the content to be
as follows:
% layout 'zurbish';
% title 'Welcome';
<h2><%= $msg %></h2>
This page was generated from the template "templates/example/welcome.html.ep"
and the layout "templates/layouts/zurbish.html.ep",
<a href="<%== url_for %>">click here</a> to reload the page or
<a href="/index.html">here</a> to move forward to a static page.
<div class="row">
<div class="small-2 columns">2 columns</div>
<div class="small-10 columns">10 columns</div>
</div>
<div class="row">
<div class="small-3 columns">3 columns</div>
<div class="small-9 columns">9 columns</div>
</div>
Now, http://localhost:3000
should give you the example text in a
very, very basic Foundation based layout. From here, you might want to
follow one of the excellent Mojolicious tutorials out there. Here is
Zurb's official guide to the Grid,
for example.
Also useful is this from "Zurb U"
which explains the small/medium/large grids. The one-line gist is:
If you don't specify small-# to a column, Foundation will assume
you mean "go full-width on small screens."
As a "Lite App"
For simplicity, here is basically the same program as a single file, in
the form of a boilerplate Mojolicious "Lite app":
#!/usr/bin/env perl
use Mojolicious::Lite;
get '/' => sub {
my $c = shift;
$c->render('index',
msg => 'Welcome to the Mojolicious real-time web framework!');
};
app->start;
__DATA__
@@ index.html.ep
% layout 'zurb';
% title 'Welcome';
<div class="row">
<h2><%= $msg %></h2>
<div class="small-2 columns">2 columns</div>
<div class="small-10 columns">10 columns</div>
</div>
<div class="row">
<div class="small-3 columns">3 columns</div>
<div class="small-9 columns">9 columns</div>
</div>
@@ layouts/zurb.html.ep
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<!-- Zurb Foundation stuff -->
<meta name="viewport" content=
"width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/foundation.min.css">
<script src="js/vendor/modernizr.js"></script>
<!-- end Zurb -->
<title><%= title %></title>
</head>
<body>
<script src="js/vendor/jquery.js"></script>
<script src="js/foundation.min.js"></script>
<script>
$(document).foundation();
</script>
<%= content %>
</body>
</html>
If you save the above as example.pl
for example, then the command
morbo example.pl
should permit you to view the generated one-page site at http://localhost:3000
Next steps
In the next installment,
we will see how to better use Mojo's template system with Foundation.
Additional Resources
This turns out to be amazingly easy, at least with Debian 7.3.
First, instead of MySQL, I followed instructions at the MariaDB site: Setting
Up MariaDB Repositories.
Then:
$ sudo apt-get install libcatalyst-modules-perl
which installed over 200 modules, but what do you know:
$ catalyst.pl Foo
creates a Foo Catalyst application under the current directory.
Everything *Just Works. *Thanks to Debian and the folks who bring you
Catalyst.
Further reading:
UPDATE (April 2014): Catalyst seems a bit heavy for most of my needs.
I'm exploring mojolicious.