Zero to Mojolicious, Part 2: Content-Wrapping Filter Templates

Tags:

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!

Command Line Tools for System Monitoring

Tags:

From TecMint this guide on 20 useful administration tools. You have probably seen some of them, but there are a few gems I hadn't run across in all my years of Linux:

Perl 5.21 cpanm fails to install DBIx::Connector

Tags:

As you may find if you use a very recent environment with perlbrew, The latest Perls do not contain CGI.pm, so when you attempt to use cpanm (CPAN minus) to install a module like DBIx::Connector, it will fail and you will see in the created log file a line that contains:

Can't locate CGI.pm in @INC (you may need to install the CGI module)

This turns out to be, if you trace it, because the test module Test::MockModule still has a CGI based test. You can make the desired module install by forcing the Test component to install anyway:

$ <span style="text-decoration: underline;">cpanm Test::MockModule --force
</span><em>(succeeds)<span style="text-decoration: underline;">
</span></em>$ <span style="text-decoration: underline;">cpanm DBIx::Connector
</span><em>(succeeds)</em>

That's really all there is to it.

WPJax September 2014

Tags:

My notes from this month's "WordPress Sampler" meeting of WPJax at Modis. Folks in our group range from business owners and students to advanced developers. Here are some of their recommendations and insights, primarily from Elizabeth, Clint, and Jonathan.

Themes and Development

Stock Photos and Shopping

Sites:

Jonathan also shared his experience finding, tracking, and repairing a bug in the WordPress Core that has existed for years.

I encourage you to contact Clint, Jonathan, or Elizabeth for your WordPress design needs. And thanks again to Modis and to Tim and Rebecca for the venue and the refreshments!

Good questions and a bunch of tips from everyone else attending rounded out this excellent session. We've got a great group going, and much talent on the move here in the "Bold New City of the South!"

SSH login without a password

Tags:

If you are using Linux and OpenSSH to automate your tasks, you will almost always find it easier to have an automatic login that does not require a password. This is especially true if you are using something like rcp for easy file transfers.

Let's configure SSH (version 2) with a secure key to bypass password login from host A / user a to Host B / user b.

Step by step

First login on system A as user a and generate a pair of authentication keys. Do not enter a passphrase:

a@A:~> ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/a/.ssh/id_rsa): 
Created directory '/home/a/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/a/.ssh/id_rsa.
Your public key has been saved in /home/a/.ssh/id_rsa.pub.
The key fingerprint is:
3e:4f:05:79:3a:9f:96:7c:3b:ad:e9:58:37:bc:37:e4 a@A

Now use ssh to create a directory ~/.ssh as user b on B. (The directory may already exist, which is fine, although in that case you may have to manually reset the mode with chmod 700 ~/.ssh ):

a@A:~> ssh b@B mkdir -p .ssh -m 700
b@B's password: 

Finally append a's new public key to b@B:.ssh/authorized_keys and enter b's password one last time:

a@A:~> cat .ssh/id_rsa.pub | ssh b@B 'cat >> .ssh/authorized_keys2'
b@B's password: 

From now on you can log into B as b from A as a without password:

a@A:~> ssh b@B

If that does not work, from system A do:

a@A:~gt; ssh b@B 'chmod 640 ~/.ssh/authorized_keys2'

and you should be good to go.