Getting Started With BeepBeep
A coworker (need to figure out his hidden blog so I can link back to him... :) forwarded a message my way from an Erlang mailing list regarding BeepBeep, which seemed like a fairly exciting project given that it combines something I am using at work but need more practice with--Erlang--and flavors it with a familiar spice: Django.
This tutorial will walk through installation, creation and (kind-of, sort-of, but not really) deployment of an extremely simple BeepBeep application. I can't promise you'll be immediately overwhelmed with excitement, but this will pave the way for more exciting tutorials down the line.
Please note that this tutorial owes a heavy debt to the BeepBeep documentation, and wouldn't have been possible without it.
In this tutorial we will build a simple web application that will display random prime numbers (my standard for webapps seems to have fallen a bit low these days), while displaying the basic components of a BeepBeep app. Without further ado, let's get started.
Installing BeepBeep
First, install Erlang. For OS X with Port this could be
sudo port install erlang
, for Debian systems it could beapt-get install erlang
.Next, download the source code from the Git repository.
cd ~/git/ git clone git://github.com/dmitriid/beepbeep.git
(At the time of this tutorial's writing, the latest commit was
96fb57a58322aa9abd0340755f0c94d6501d223d
from July 2nd, 2009. If you really want this tutorial to work without modification, I'd recommend using that version.)Third, we need to build the BeepBeep source code. (The Git repository is kind enough to come with its dependencies--MochiWeb and ErlyDTL--included.)
cd beepbeep make
Somewhat unusually, building the code worked on the first try, and didn't involve chasing down any hidden dependencies.
Now you've completed the rather painless BeepBeep installation.
Creating a BeepBeep Project
Now that we've installed the framework, our next step is to create the foundation of our new project.
First, create the project scaffolding for the
BB_Primes
, the exceedingly unclever name for the project we're building../script/new_beep.erl Primes ../BB_Primes
Now start the webserver for the new project.
cd ../BB_Primes/primes/ make ./stat_server.sh
If you forget to
make
the code you'll get a fairly generic crash file, so double-check there first if something goes wrong.After successfully running the server, go to http://localhost:8000 to view the default BeepBeep application page.
Now let's take a few minutes to take a look at the various files and folders that are created by the
new_beep.erl
script.deps
contains the BeepBeep, MochiWeb and and ErlyDTL sources, which means you don't need to ensure those are in your Erlang path. Not too much to do here, although you might want to add other dependencies your project uses.ebin
stores the compiled files generated by theMakefile
. Not much to do here either.support
containsinclude.mk
, a helper file formake
.www
contains static files to be served by MochiWeb. (I must admit, I assumed a production environment using BeepBeep would involve hiding it behind Nginx/Lighttpd and only using it to serve dynamic content, but it seems that MochiWeb is a reasonable static file server as well.)views
contains the templates used to render to your apps pages. These templates are written in the Django template language, compiled using ErlyDLT.src
contains all the code for the application, including several pieces that will be unfamiliar to those without previous Erlang experiences.home_controller.erl
is where your controller logic is defined. For simple applications, this is the only file in src that you'll need to edit.primes.app
defines an OTP application.primes.erl
defines the start and stop functions forprimes.app
.primes_deps.erl
defines and locates dependencies (I haven't actually seen aX_deps.erl
file before, a rather nice idea for reusable apps.)primes_app.erl
starts and stops theprimes_sup.erl
supervisor application.primes_sup.erl
defines the supervisor forprimes.app
.primes_web.erl
defines the MochiWeb server for the app.
Customizing a BeepBeep Project
There are three primary locations where you'll be making changes to your BeepBeep projects.
src/home_controller.erl
is where URL patterns and behavior are defined. In Django terms, it serves as both theurls.py
andviews.py
files for your project.views/
contains all templates, which are used by controllers to display content to users. In Django, this would be yourtemplates/
folder.www/
contains all static media, akin to themedia/
folder for most Django projects.
In general, I would recommend starting with a simple controller, writing a simple view to match, and then iterating between the two until reaching your desired ending point. Finally add static files at the very end.
Following my own advice, first let's open up src/home_controller.erl
.
Find the index handle which looks like this:
handle_request("index",[]) ->
{render,"home/index.html",[{data,"Hello There From BeepBeep!"}]};
and modify it to look like:
random_prime(N) ->
% skipping the logic for finding
% nth prime to keep things concise ;(
101.
handle_request("index",[]) ->
N = random:uniform(100),
SomePrime = random_prime(N),
{render, "home/primes.html", [{prime, SomePrime}]};
Next it is time to work on our views. First open up
views/base.html
.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<title>Welcome to Primes</title>
<link href="/stylesheets/style.css" rel="stylesheet" type="text/css"/>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
The base.html
template is used as scaffolding for other templates, and is a
simple way to support the Don't Repeat Yourself philosophy from Django.
We will then extend it into the home/primes.html
template.
{% extends "../base.html" %}
{% block content %}
<p>Prime is : { { prime }}</p>
{% endblock %}
Now finally make
the application again.
will-larsons-macbook:primes will$ make
(cd src;make)
erlc -W -I ../include -I ../deps/beepbeep-src/include -pa ../deps/beepbeep-src/ebin -pa ../deps/erlydtl-src/ebin -pa ../deps/mochiweb-src/ebin +debug_info -o ../ebin home_controller.erl
./home_controller.erl:8: Warning: variable 'N' is unused
Woops, have a warning there because I backtracked on implementing the prime code, but nothing too important.
Now start the server again:
./start-server.sh
If you had (hypothetically, of course) typoed home/prime.html
instead
of home/primes.html
in your controllers file, then you would see
an error like this:
It isn't quite as pretty or as informative as the Django error pages, but it's servicable nonetheless. A successful run looks like this:
Right now it is using the default BeepBeep stylesheet at
www/stylesheets/style.css
, but let's change things
up ever so slightly.
emacs www/stylesheets/primes.css
And add these styles:
body {
padding: 25px;
background: #333;
color: #BBF;
}
Then edit views/base.html
to replace
<link href="/stylesheets/style.css" rel="stylesheet" type="text/css"/>
with
<link href="/stylesheets/primes.css" rel="stylesheet" type="text/css"/>
Now restart the server,
./start-server.sh
reload the page, and bask in the glory of the very simple application you have created.
Deployment
The current start script runs in the current shell session, which is great for development, but less convenient for long-running processes. You could go very far in improving it (start it in an alternate node, run it using heart, etc), but keeping with the simple tone of this tutorial it is easy to simply run it in detached mode which allows you to retain your shell sessions.
cp start-server.sh start-detached-server.sh
emacs start-detached-server.sh
Then modify start-detached-server.sh
to look like this:
#!/bin/sh
cd `dirname $0`
exec erl -pa $PWD/ebin $PWD/deps/*/ebin -boot start_sasl </span>
-s reloader -s primes -detached
If you want the process to persist after you logout, you can use sudo -u
to run the
process as a persistent user (running as root
has some ever-so-minor security consequences, but one might use www-data
or a custom user to run your BeepBeep app).
So there you have it, a very simple BeepBeep application. This tutorial admittedly doesn't give you the Blog in 5 Minutes feel that you've probably come to expect from frameworks, but hang around and I promise the next BeepBeep tutorial will be much more exciting.
(The code from this tutorial is available as BB_Primes
in the BeepBeep Examples git repository.
As always, I am grateful for any feedback or corrections!