Building a web-site with Dancer

[ Perl tips index ]
[ Subscribe to Perl tips ]

Building web-sites used to be lots of work. To begin with, you'd need to install a web server. Then you needed to figure out sessions, and cookies, and parsing URLs. If you were lucky, you had a framework to handle all those things for you.

But one of the best things about Perl is that you can often sit down and start writing code straight away. Wouldn't it be great if we could do the same with websites?

Well, with Dancer, you can.

Hello World

Writing a basic web-server in Dancer is pretty darn easy:

    use Dancer;

    get '/' => sub {
        return 'Hello World!';
    };

    start;

Dancer comes with its own web-server for rapid development, so running this code is as simple as saving it to a file and running it:

    $ perl hello.pl

    >> Dancer 1.3095 server 14364 listening on http://0.0.0.0:3000
    == Entering the development dance floor ...

Then we just point our web browser at http://localhost:3000/ and enjoy our Hello World message.

One of the best things about Dancer is how easy it is to make use of path information. If part of a path begins with a colon, it's captured and becomes accessible via the param keyword:

    get '/user/:name' => sub {
        my $username = param('name');
        return "Hello $username!";
    };

Now, accessing http://localhost:3000/user/Dancer will return Hello Dancer!

Writing our own twitter

To provide a basic example of using Dancer, we're going to write a bare-bones twitter clone, which we'll call Trillr. We'll use DBD::SQLite for our database, with an incredibly simple schema:

    create table if not exists trills (
        time  integer      not null,
        user  varchar(12)  not null,
        trill varchar(140) not null
    );

Homepage

We'd like our homepage to simply show what trills have been made thus far. This is similar to our hello world example above, except we're going to use a template for formatting:

    set template => 'template_toolkit';

    get '/' => sub {
        template 'trills.tt', {
            trills => get_trills(),
            title  => 'Trillr',
        };
    };

The set keyword allows us to set parameters in Dancer. In this case, we're saying that we're going to be using Template::Toolkit as our templating engine.

The template keyword has Dancer look inside the views/ directory for the specified file - in our case, that's trills.tt. The hash reference passed to template provides parameters to our template; in this case, we're passing the results from get_trills() (which we'll see later), and a title of 'Trillr'.

For the moment, our template consists of:

    <ul class="trills">
        <% FOREACH trill IN trills %>
            <li class="trill">
                <a href="/<% trill.user %>">@<% trill.user %></a>
                <% trill.trill %><br />
                <span class="time">Trilled at: <% trill.time %></span>
            </li>
        <% END %>
    </ul>

User pages

Writing a user page is simply a matter of matching a path and only showing trills for that user:

    get '/user/:name' => sub {
        my $name = param('name');

        template 'trills.tt', {
            user   => $name,
            trills => get_trills($name),
            title  => "Trills for $name",
        };
    };

Here we're using the same template as before, but we're also passing in a username, and only getting the trills for that user. At the top of trills.tt we've added:

    <% IF user %>
        <div class='trill_me'>
        <form method="POST">
            <p>Trill me: <input type='text' name='trill' /></p>
        </form>
        </div>
        <p class='trills_for'>Trills for <% user %></span>
    <% END %>

This provides a simple Trill me input if we're on a user's page. Since this is a bare-bones example, we're not going to do any authentication; if you post to this page, then you'll post as the user in question. But how do we post?

Trilling

In the same way that we can use Dancer's get keyword to process GET requests, we can use the post keyword to interpret POST requests.

    post '/:name' => sub {
        my $trill = param('trill');
        my $name  = param('name');

        if (not $trill) {
            send_error("No trill supplied");
        }

        if (length($trill) > MAX_LENGTH) {
            send_error("Trill too long");
        }

        insert_trill($name,$trill);

        return forward "/$name", { trilled => 1 }, { method => 'GET' };
    };

Here we're getting our username from the path, and our trill from the post operation. We're doing some basic error checking, then using insert_trill (discussed later) to insert that into our database. The send_error function is provided by Dancer. We can define a custom error page if we like, but in this example we'll stick to the default.

The particularly cool part of this is the return forward section at the end. This internally re-writes the user's request as if they've done a GET request for /$name, passing control back to the get '/:name' subroutine we defined above. The trilled = 1> hashref allows us to define an extra param, which we could use to flash a message, change behaviour, or otherwise say "Thanks for trilling".

Layouts

When building a website, we'd like to provide common elements on each page. Headers, style sheets, navigation, a copyright notice. Dancer allows us to supply a layout setting, which will wrap any template we use. Setting a layout is easy:

        set layout => 'default';

In this case, we're calling our layout default. Our application may have different layouts for different users, sections, or states.

If we've set a layout, then Dancer goes looking in the views/layouts/ directory, and automatically appends the appropriate template extension to our layout name; in our case, it would open views/layouts/default.tt.

Our layout simply provides a bare-bones wrapper and some style-sheet information:

    <!doctype html>
    <html>
    <head>
        <title><% title %></title>
        <style type="text/css">
            .time  { font-size: smaller; }
            .trill { background: #afa; }
            .trill:nth-child(odd) { background: #aaf; }
        </style>
    </head>
    <body>
    <h1><a href="/">Trillr</a></h1>
    <% content %>
    </body>
    </html>

The big thing to note here is the <% content %> section. This is where our actual content gets inserted. It's also worth noting this is where our <% title %> gets used, which we've seen passed into the templating engine in our previous examples.

Get the source

You can clone the source code for trillr from github using:

    git clone git://github.com/pjf/trillr.git

or you can view the repository on-line at https://github.com/pjf/trillr.

We haven't shown the get_trills() and insert_trill() functions here, because they're not core to using Dancer, but you can find them (and more) by browsing the source code above.

Find out more

Dancer can do a lot more than what we've shown in this example. Sessions, rich database access, integration with Plack, debugging and logging facilities, and dozens of plug-ins. Best of all, Dancer is free and open source.

For more information, head over to the Dancer website at: http://perldancer.org/.

See Also

[ Perl tips index ]
[ Subscribe to Perl tips ]


This Perl tip and associated text is copyright Perl Training Australia. You may freely distribute this text so long as it is distributed in full with this Copyright noticed attached.

If you have any questions please don't hesitate to contact us:

Email: contact@perltraining.com.au
Phone: 03 9354 6001 (Australia)
International: +61 3 9354 6001

Valid XHTML 1.0 Valid CSS