Mojo Wonk Blog.

A semi-offical blog dedicated to the Mojolicious web framework

Yancy's Static Backend

An old book with a cloud and "Mojolicious"

Back a few months ago I wrote about making a website for the Yancy CMS that included a basic Markdown page editor, adding a documentation viewer with the Mojolicious PODViewer plugin, and deploying a static version of the site using the Mojolicious export command. The site uses a SQLite database, which makes it very easy to set up and use the Yancy editor, but very difficult to work with the data any other way...

To solve this problem, many people have taken to writing their website as a set of static files and using a static site generator to add templates and plugins to build their website. Each page has a header section that defines some metadata about the page, like the title or the date it was posted. Instead of having each page be a row in a SQLite database, each page in a static site is a file on the filesystem!

Yancy uses "Backends" to interface with a database. To make Yancy into a static site generator, I wrote a backend that works with a flat-file database made up of YAML and Markdown files: Yancy::Backend::Static. I can use this new backend to make my Yancy documentation site even easier to edit!

Continue reading Yancy's Static Backend...

Testing Environment With Tmux

Text saying "Tmux" in the middle of white, red, yellow, and blue boxes containing shell output separated by thick black lines. Original artwork by Doug Bell

The Yancy CMS for the Mojolicious web framework currently supports three different database systems directly (and even more through the DBIx::Class ORM). As a result, when doing development, I need to have two database daemons running locally, a bunch of different environment variables to tell the tests where those databases are, and a web daemon to test the front-end.

Setting up these daemons is a pain, but I also do not want to run them all the time (to save on my laptop's battery). To me, it's easier to run a database daemon for a specific project than to try to manage all the databases I might need. But that means that every time I want to do some work on Yancy, I need to start up a bunch of things.

Since I do all my development in a terminal window, the Tmux terminal multiplexer has become an extremely useful tool. Using a shell script and Tmux, I can run a single command to set up all the databases, environment variables, and all the tabs I need to get to work quickly.

Continue reading Testing Environment With Tmux...

Reverse Proxy With Path

Clouds with arrows pointing back and forth on a blue background

It's extremely common for a Mojolicious web application to be hosted behind some kind of HTTP proxy: A production website usually includes Varnish, or Nginx, or a CDN (probably using Varnish or Nginx).

In the most common case, a web application is the entire domain, so configuring the reverse proxy is very simple: Add the -p option to hypnotoad or myapp.pl daemon command, or set the MOJO_REVERSE_PROXY environment variable to a true value. See the Mojolicious Cookbook for more details.

But what if my application doesn't have its own domain? How do I host a Mojolicious application as a reverse proxy from a path in another domain?

Continue reading Reverse Proxy With Path...

Mojolicious and DBIx::Class

Mojolicious (heart) database on a pink background. Original artwork by Doug Bell

Mojolicious is an MVC framework. But, unlike Catalyst, Mojolicious does not provide a model API. This is a good thing: Mojolicious works well with any model layer, including the existing models used by your current application.

DBIx::Class is a popular model layer for Mojolicious applications. DBIx::Class (or "DBIC") is an Object-Relational Mapper (ORM) to map objects onto a relational database. This allows for a well-organized model layer, and a standard API to access the data.

For those who read last month's posts on Writing Reusable Controllers and Writing Extensible Controllers, this post introduces the end result of those posts: The Mojolicious DBIC Plugin. This plugin makes it easier to start using DBIx::Class with Mojolicious.

Continue reading Mojolicious and DBIx::Class...

Writing Extensible Controllers

Clouds stacked inside clouds, mixed with gears. Original artwork by Doug Bell

Once I have a reusable controller, how do I extend it? Object-oriented programming gives me a couple ways of extending a controller through code: Inheritance and composition. But, we need to write our controller so that it's easy to inherit or compose.

Don't Render, Stash

First, this means we shouldn't call the render method ourselves (unless we have a good reason, but we'll get to that later). The render method can only ever be called once, so we should only call it after we've gathered all the data we want.

# This method cannot easily be used by a subclass, since it explicitly
# calls render()
sub list {
    my ( $c ) = @_;
    my $resultset_class = $c->stash( 'resultset' );
    my $resultset = $c->schema->resultset( $resultset_class );
    $c->render(
        resultset => $resultset,
    );
}

So, to make sure I don't call render too early, and to make sure subclasses can use the data from my superclass, I instead put all the data directly in to the stash with the stash() method.

Continue reading Writing Extensible Controllers...