The Elixir MVC Framework Phoenix
This blog post will show how a functional web application can be built with Elixir and Phoenix in a few, simple steps, without requiring a deeper understanding of functional programming or the Erlang/OTP system.
A small demo application will then help us understand how the Phoenix framework works and appreciate the technical merits of the Elixir ecosystem.
Follow–up blog posts will provide deeper insights into the framework and its components, such as Plug or Ecto. Special attention will be paid to connecting the web application with the document database CouchDB.
Phoenix, Elixir, CouchDB
Elixir is a dynamic, functional programming language that leverages the Erlang VM (BEAM). It has a modern syntax that borrows from languages such as Ruby and supports advanced meta programming features, facilitating a smooth entry into the world of Erlang and its interesting runtime characteristics.
Erlang is a functional programming language that has been developed to build highly available, “always–on” systems in the telecommunications domain.
It is well known for its resilience, its transparent approach to building distributed systems and a developer friendly handling of concurrency (Actor Model).
The ecosystem around Elixir is still comparatively small, but is being quickly developed by a growing community of enthusiasts.
The web application framework Phoenix is one of the products that this community has spawned. It greatly simplifies the development of high–performance HTML5 apps, API–Backends and websocket applications.
When we first checked out Phoenix, it became apparent that database adaptors exist mainly for relational databases and MongoDB.
In order to stay within the Erlang ecosystem and to leverage the features of a document database, we decided to integrate with CouchDB.
CouchDB is a NoSQL database, developed in Erlang, that stores JSON documents and exposes its functionalities through an HTTP API.
Having found no readily available database connector that fulfilled all of our requirements triggered our decision to develop our own CouchDB connector in Elixir.
The current release of this connector supports basic create, update and read operations, as well as rudimentary view operations.
The code has been published as an open source project on Github.
Starting a Phoenix Project
In order to bootstrap a new Phoenix project, we make use of the Elixir command line tool mix and apply one of the tasks defined by Phoenix, in this case:
mix phoenix.new <app-name>
As we do not want to make use of a relational database, we exclude the default persistence layer Ecto by adding the –no-ecto flag. So, in order to create a project with name ‘foo’, we type:
mix phoenix.new foo --no-ecto
After creating the files and folders that make up the project structure, the mix tool prompts us to download and install a set of dependencies — later on we will see where these are declared.
Change into the project root:
We now have several options to start the application. To allow interaction with the application’s modules at runtime, we start the application within a REPL (Read–Eval–Print Loop), using Elixir’s interactive shell, iex:
iex -S mix phoenix.server
This brings up the (as yet empty, but fully functional) application, so that we can now reach it through a web browser on port 4000:
We will be greeted with the page shown below.
Phoenix has a very useful Live–Reload feature. A change that we make in the currently shown page will immediately become visible in the browser, without us having to manually trigger a reload of the page.
Assuming the application is in the state shown above and we change the underlying HTML template in
the web browser will immediately show the effect of that change and render the new state as shown below:
In the iex console, we will see the change being logged:
Let’s now look into some of the newly created folders:
The config folder contains project configuration files. Some dependencies also expect their configurations to be stored here, an example being credo, a static code analysis tool.
The configuration mechanism also supports different settings per environment by simply storing them in the appropriate config files: dev.exs, test.exs, etc.
These .exs files (Elixir scripts) are compiled in memory each time they are run, which makes them ideal for storing configuration details and scripts that change often during development.
Some other, less frequently changing configuration artifacts live inside the lib folder.
│ └── foo
The .ex files in this folder are compiled to .beam files and then loaded into the Erlang Virtual Machine (BEAM), which makes these files useful for storing higher level, less frequently changing configurations, such as endpoint and OTP supervisor/worker config. For performance reasons, such types of configurations should therefore be stored in lib or subfolders thereof.
The Phoenix framework implements the well–known Model–view–controller architectural pattern (MVC).
The web folder contains MVC artifacts like controllers, models and views. In contrast to other MVC frameworks, such as Ruby on Rails, Phoenix differentiates between templates and views. The Templates are getting pre–compiled, which helps to reach the high performance that Phoenix has to offer.
Routing information is stored in router.ex. It contains a mapping of request paths to controller functions.
An example configuration (brunch-config.js) can be found in the demo project, which we will introduce next.
We have thus far looked at an essentially empty, yet functional walking skeleton project, which already showed some of the ways of working with Phoenix.
However, a real–world demo application allows us to address more of Phoenix’s features and characteristics.
Such a demo application has been made available in a Github repository.
Check out the source code:
git clone https://github.com/mkrogemann/bird_watch
Here, we have made use of the mix build tool to resolve and download the project’s dependencies. mix can also facilitate creating, compiling and testing Elixir projects. We will see more of it in future episodes.
We can also use mix to pre–populate the database by calling an application specific seeding script:
mix run priv/repo/seeds.exs
Now we can start the application
and open it in a web browser:
In a small number of simple steps, we have created a functional web application and shown how easy it is to make changes that are immediately visible, thanks to the perfect implementation of Live–Reloading. This feature is a real productivity boost.
Another nice trait is the excellent performance of Phoenix web applications. Check out these impressive benchmarks to appreciate its throughput and latency figures.
We will continue development of the demo application “Bird watch” in follow–up blog posts and show more of the advanced functionalities and characteristics of Phoenix, Elixir and OTP.