Pet project with Erlang's ChicagoBoss

60 min tutorial

TL;DR

It’s about Erlang, from a Ruby on Rails perspective. I’ll teach you the basics of ChicagoBoss, an Erlang framework that looks like Rails.

“I thought of objects being like biological cells and/or individual computers on a network, only able to communicate with messages”, Alan Kay

    Watching Joe Armstrong’s talks and reading his books make us wonder about the current status of object oriented programming. We have for long abandoned Alan Kay’s idea of completely uncoupled objects, trading messages seamlessly through networks and have focused on inheritance and other inessntial characteristics as the essential features of OO. For Armstrong, and a growing group of unsatisfied developers, we have missed the point of OO, and it’s time to reconsider –just look at the emerging trend of enterprise-ready functional languages, like Scala and Clojure, and the rebirth of flow-based programming.

image
Image from Learn you some Erlang

It’s certainly true that the Ruby on Rails community, guided by the seasoned masters of Smalltalk, has created the easiest way of building web apps. Thanks to Ruby, the clearest and most flexible class-based OO language ever created.

Nevertheless, a true Ruby developer – the one who have entered Ruby just for the pleasure of learning something new and, in the path, becoming a better developer – will certainly agree with me that we shouldn’t stop here. But can Erlang teach us anything new about OO? Or about web development in general? Sure it does. The actor model implemented in Celluloid, for instance, is heavily influenced by Erlang’s. Also, lots of modern tools for creating heavily used apps are built on top of Erlang, like CouchDB, RabbitMQ and Riak, just to mention a few.

To make the learning even easier, there a couple of web frameworks written in Erlang out there. There are even Rails inspired frameworks, like ChicagoBoss. ChicagoBoss comes with the same basic scaffold of Rails: Controllers that are functions that handle the requests, mapped by routes; the models, that represent relations (a.k.a. tables) in the database; and views, that are the good n’ old templates. Of course, everything comes with a twist, and you’ll see the difference when we move along.

But ChicagoBoss is not just another Rails clone. It has features that are not among Rails’ core strenghts. Non blocking IO, websockets & long polling – the first only available throught gems, and the second only introduced in Rails 4 –, non nested callbacks (got it NodeJS?), and many more.

One more thing that may interest Ruby developers is the fact that you can write ChicagoBoss apps with Elixir. Elixir is a language heavily inspired by Ruby, created by José Valim.

So, no more intro, let’s install the beast. If you’re on MacOS you can use brew:

Shell

brew install erlang

Now let’s install ChicagoBoss:

Shell

wget http://www.chicagoboss.org/ChicagoBoss-0.8.7.tar.gz
tar -xvf ChicagoBoss-0.8.7.tar.gz
cd ChicagoBoss
make

That’s all. Now, you need to create your pet project, literally. Let’s call it “petster”, to have a fancy hipster name. So this is what we need to do:

Shell

make app PROJECT=petster
cd ../petster

I liked ChicagoBoss when
it was still underground…

So, first of all, let’s take a look at the scaffold ChicagoBoss generates. The boss.config file is the main configuration file – as config/application.rb, plus other config files like config/database.yml in Rails.

The init-dev.sh is the equivalent of the rails s command, running a server in development mode (the server-start.bat is the same, but for Windows, so just delete it! Now!).

All the rebar stuff is for installing Erlang packages, compiling – yes, unlike Ruby, Erlang is compiled – and for running unit and functional tests. Think of it like a bundle/gem and a rake test.

One more thing that may interest the Ruby developers is the fact that you can write ChicagoBoss apps with Elixir. Elixir is a language heavily inspired by Ruby, created by José Valim.

The ebin will have all the compiled binaries after you do your first compilation.

The priv has lotsa stuff, from routes, to migrations to static assets – equivalent to config/routes.rb, db/migrations/* and app/assets, respectively.

And finally the src folder, that includes all controllers, models, views, tests, emails, libs and websockets handlers of your app. Think of it of an app but on hard steroids. And there’s no need to talk about log, right?

Once we know a bit about the structure of the project we can start the hello world All you have to do is to create a file inside the src/controllers folder, following the convention {application_name}_{controller_name}_controller.erl. In our example, the file will be src/controllers/petster_hello_controller.erl. And this is the code:

src/controller/petster_hello_controller.erl
1
2
3
4
5
-module(petster_hello_controller, [Request]).
-compile(export_all).

world('GET', []) ->
  {output, "This is not a hello world"}.

The first line defines an Erlang module, which is, roughly speaking, the class MyController < ApplicationController in your Rails project. While petster_hello_controller is the actual name of this controller, Request is a variable (at this point you should already be aware that variables are camel case in Erlang, and haven’t given up ‘cause of that!) that receives… the request. Think of it as a request, plus a params in Rails, with the difference that you have to call a function to get ‘em.

The second line exports all functions defined in the controller. In Erlang you can define, for each module wich functions are available or not. This is pretty much what public and private gives you in Ruby.

And finally, the fourth and fifth lines define a function called “world”, acessible through the “get” http verb. If the ‘GET’ string in the definition of the function looks odd to you is because you need to understand Erlang’s pattern matching (beware: this has nothing to do with regular expressions!). This funcion basically return a touple that informs ChicagoBoss to directly output the given string, without rendering any view.

In order to test it we have to start the development server. As we have already seen, all we gotta do is to run:

Shell

./init-dev.sh

And now you can access it at http://localhost:8001/hello/world.

noSQL hipster

This is really trivial, so let’s move to a CRUD (create, read, update & delete) for the pets (actually I’ll just show you the CR, and you’ll have to do the UD for yourself :D). The first step is to configure the database. ChicagoBoss supports out-of-the-box many databases, like PostgreSQL, mySQL, Riak, MongoDB, Tokyo Tyrant and Mnesia, Erlang’s default database.

I’ll be using PostgreSQL, because noSQL is so mainstream now, that PG is the new underground. Change your boss.config to include the following:

boss.config
1
2
3
4
5
{db_host, "localhost"},
{db_port, 5432},
{db_adapter, pgsql},
{db_username, "petster"},
{db_database, "petster_dev"},

Don’t forget to actually create a user named ‘petster’ and a database named ‘petster_dev’.

The second step is to generate a migration. Migrations in ChicagoBoss are similar to Rails’ but with a downside, you gotta use SQL (yucc!). You also have generators to create migrations, but unlike Rails you don’t run generators in the terminal, you run ‘em inside the Erlang shell. So, in the same window you started the server you also have an interactive Erlang thing. You can debug your app and run commands there. So, let’s create our migration:

Erl

boss_migrate:make(petster, pets).

This will generate a file inside priv/migrations, with this initial code:

priv/migrations/1384894713_pets.erl
1
2
3
4
5
6
%% Migration: pets

{pets,
  fun(up) –> undefined;
     (down) –> undefined
  end}.

Just like Rails you have up and down methods, so you can run migrations and rollback as necessary. Let’s define the table like this:

priv/migrations/1384894713_pets.erl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
%% Migration: pets

UpSQL = "
  CREATE TABLE pets(
    id serial unique,
    name text not null,
    species text not null
  );
".

DownSQL = "DROP TABLE pets;".

{create_pets,
  fun(up)   –> boss_db:execute(UpSQL);
     (down) –> boss_db:execute(DownSQL)
  end}.

Basically I’m defining two variables, UpSQL and DownSQL with the SQLs, and I’m executing ‘em in the database using the boss_db module. Again, I’m usign Erlang’s pattern matching so set an anonymous funcion – fun is the equivalent of a proc/lambda in Ruby – with two different input types, up and down. These are atoms, but think of ‘em as Ruby’s symbols.

And now, let’s run the migration, inside the Erlang process again:

Erl

boss_migrate:run(petster).

You should receive a {atomic,[ok]} response, if the migration ran successfully.

Now we can create the model file for this table. Let’s create a file named src/model/pet.erl, and let’s write this code in it:

src/models/pet.erl
1
2
module(pet, [Id, Name, Species]).
compile(export_all).

As you can infer from this code, ChicagoBoss models do not discover the table’s attributes automatically. You have to define ‘em in the module. If you need more methods in the model, you create them in this file, just like Rails.

At last, but not the least, let’s create the controller for the pets:

src/controller/petster_pet_controller.erl
1
2
3
4
5
6
module(petster_pet_controller, [Request]).
compile(export_all).

index('GET', []) –>
  Pets = boss_db:find(pet, []),
  {ok, [{pets, Pets}]}.

The boss_db:find is responsible for searching the database, just like a Pet.all in Rails. The second param – an empty array – is used for filter, sorts and other SQL decorations.

The ok response basically tells ChicagoBoss to look for a view. The views follow the Rails convention, existing in the src/views/controller/function.html. And the {pets, Pets} sends the variable “pets” to the view, so it can be used there, just like when you set instance variables inside a Rails controller.

So let’s go to the views. In ChicagoBoss, the default templating system is inspired by Django. So you don’t have something like ERB, and you’ll have to read a lil of Django’s Templates documentation to figure out how to do stuff. Oh, by the way, this language is called ErlyDTL. There are also other options, like Jade, wich is the equivalent of HAML/Slim. Anyway, so far I have kinda enjoyied using ErlyDTL, specially in the way it handles the distinction of layouts and views. I also believe that Django Templates approach is more designer friendly, and may be better for projects requiring intensive design collaboration. We can start by creating a layout:

src/view/app.html
1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Petster</title>
  </head>
  <body>
    {% block content %}{% endblock %}
  </body>
</html>

The block content is the equivalent of a yield :content in Rails. There is no equivalent of a simple yield, you always have to name the placeholders of content. Another difference is that you can have content inside these placeholders, as defaults, that’s why they’re blocks. The view for the index action will be something along these lines (you’ll have to create the “pets” folder inside src/view):

src/view/pets/index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{% extends "app.html" %}
{% block content %}
<a href="{% url action="new" %}">
  New
</a>

<table>
  {% for pet in pets %}
    <tr>
      <td>{{ pet.name }}</td>
      <td>{{ pet.species }}</td>
      <td>
        <a href="{% url action="edit"
                        id=pet.id %}">
          Edit
        </a>
      </td>
    </tr>
  {% endfor %}
</table>
{% endblock %}

We start by extending the app layout and defining the content – like a content_for :content. Inside the content we iterate throught the pets list and present the name, the species and a link to the edit action. The url function is a helper, similar to url_for. The pet.name syntax is not standard Erlang. It’s introduced by ChicagoBoss to simplify the way you call model “methods”. Now add some items in the database, head to http://localhost:8001/pets/index and see the result.

Now let’s talk about routes. So far we have just created controllers and actions and routes appeared magically. But let’s say we want the index of pets to be the root path of our app. We need to edit the priv/petster.routes to have the following line:

priv/petster.routes
1
{"/", [{controller, "pets"}, {action, "index"}]}.

Pretty easy, hum?

Now let’s go to the creation of pets. We start by defining a “new” view:

src/view/pet/new.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{% extends "app.html" %}
{% block content %}
<form action="{% url action="create" %}"
      method="post">

  <input name="name" placeholder="Name" />
  <select name="species">
    <option value="dog">Dog</option>
    <option value="cat">Cat</option>
    <option value="wolf">Wolf</option>
  </select>
  <input type="submit" />
</form>
{% endblock %}

Notice there’s no need to define an action in the controller if it’s a ‘GET’ and we’re not passing down info to the view. The route will be created based on the existance of the view.

And this is the create action:

src/controller/petster_pet_controller.erl
1
2
3
4
5
6
7
8
create('POST', []) –>
  Name = Request:param("name"),
  Species = Request:param("species"),

  Pet = pet:new(id, Name, Species),
  Pet:save(),

  {redirect, "/"}.

Hipster wolf as a pet?

When the form is posted, we get the params and pass ‘em to the new method of pet model. The id is just an atom to inform the model to use the auto incremental value instead of setting an id. In the last line we tell the app to redirect back to the root.

Now it’s up to you to complete the CRUD. Take a look at ChicagoBoss docs and implement the update and the delete actions.

These are the basics of ChicagoBoss. Of course there’s a lot more to do, even in such a simple project, like testing the app, validating the data in the model, and so on… All the code of this tutorial is available at https://github.com/joaomilho/petster. If you wanna try something a little more advanced take a look at https://github.com/joaomilho/apalachin and join ChicagoBoss’ mailing list.




Comments