Posts in this series


Alright! Let’s get busy! In this article we’ll install Elixir, Phoenix and all the other bits we need for our Banking API project. I’m a Linux user at home, and aware of macOS since I use it at work, but no idea about Windows support since I haven’t used it for development for a long time.

If you already have Elixir and Phoenix installed, skip over this section

Let’s get started. You’ll need:

  • Elixir
  • PostgreSQL
  • Phoenix

I tend to avoid Linux distro packaging of programming languages, since they usually evolve faster than distro release cycles - especially true for Debian, notorious for lagging behind quite a bit on its stable channel. So let’s use a “version manager” to install languages locally. I used to be a big fan of RVM and nvm but they’re specific to Ruby and nodeJS, respectively, which is a bore because you need to learn N tools to manage N languages.

Enter asdf, which exposes a stable interface to manage all of its supported languages and supports bash, ZSH and Fish (my shell of choice). If you don’t want to use asdf, feel free to install Erlang (21+) and Elixir (1.8+) by other means. On macOS, homebrew is usually quite quick with updates, and the community is quite active with fixes, but I’d still suggest using asdf.

Installing asdf is quite easy. Clone it locally:

$ git clone ~/.asdf --branch v0.6.3

Then, if you use bash, do:

$ echo -e '\n. $HOME/.asdf/' >> ~/.bashrc
$ echo -e '\n. $HOME/.asdf/completions/asdf.bash' >> ~/.bashrc

or with fish:

$ echo 'source ~/.asdf/' >> ~/.config/fish/
$ mkdir -p ~/.config/fish/completions; and cp ~/.asdf/completions/ ~/.config/fish/completions

and open a new terminal or terminal tab to load it. Check it’s installed with:

$ asdf --version

Next up, we’ll install the Erlang and Elixir plugins:

$ asdf plugin-add erlang
$ asdf plugin-add elixir

There are a few build requirements for Elixir and Erlang. For Debian:

$ sudo apt install curl build-essential autoconf m4 libncurses5-dev libwxgtk3.0-dev libgl1-mesa-dev libglu1-mesa-dev libpng-dev libssh-dev unixodbc-dev xsltproc fop

The Erlang plugin’s README has more info on package names for other distros and macOS. Let’s install the most recent 21.x version (this will take a while):

$ asdf install erlang 21.2.6
$ asdf global erlang 21.2.6 # sets this version as default

And the most recent Elixir version (this will be super quick):

$ asdf install elixir 1.8.1-otp-21
$ asdf global elixir 1.8.1-otp-21 # sets this version as default

You’ll also need PostgreSQL for our databases (read model and event store). For this I suggest you do use your distro’s packages, and if you’re on macOS is pretty good. Be sure to use at least version 9.6, ideally 11.

The final piece is the Phoenix web framework, which will handle all the HTTP busywork on our project. I won’t give a full introduction to Phoenix, since our interaction with it will be very small. Installation is pretty simple. We’ll need Hex, the Elixir package manager first:

$ mix local.hex

Then the Phoenix command line tools:

$ mix archive.install hex phx_new 1.4.1

Phoenix uses webpack to bundle Javascript and CSS assets, so you could install the nodeJS asdf plugin, but our project won’t be using any web assets, so feel free to skip it.

If you want live-reloading of code in development (and you should, it’s amazing), you’ll need to install inotify-tools. For Debian:

$ sudo apt install inotify-tools

Check its wiki for info on setting it up for other distros.

And that’s it, we’re all set!

Getting Started

Let’s create our project folder. Elixir ships with Mix, a powerful mix of task runner and dependency fetcher. Having it built-in to the language is a huge boon for productivity. Phoenix’s command line tools are invoked using it.

To create out project in a bank_api sub-folder:

$ mix bank_api --module BankAPI --database postgres --no-webpack --no-html

We set the main module name, PostgreSQL as the database, skip webpack and HTML views.

This is what you should see:

* creating bank_api/config/config.exs
* creating bank_api/config/dev.exs
* creating bank_api/config/prod.exs
* creating bank_api/config/prod.secret.exs
* creating bank_api/config/test.exs
* creating bank_api/lib/bank_api/application.ex
* creating bank_api/lib/bank_api.ex
* creating bank_api/lib/bank_api_web/channels/user_socket.ex
* creating bank_api/lib/bank_api_web/views/error_helpers.ex
* creating bank_api/lib/bank_api_web/views/error_view.ex
* creating bank_api/lib/bank_api_web/endpoint.ex
* creating bank_api/lib/bank_api_web/router.ex
* creating bank_api/lib/bank_api_web.ex
* creating bank_api/mix.exs
* creating bank_api/
* creating bank_api/.formatter.exs
* creating bank_api/.gitignore
* creating bank_api/test/support/channel_case.ex
* creating bank_api/test/support/conn_case.ex
* creating bank_api/test/test_helper.exs
* creating bank_api/test/bank_api_web/views/error_view_test.exs
* creating bank_api/lib/bank_api_web/gettext.ex
* creating bank_api/priv/gettext/en/LC_MESSAGES/errors.po
* creating bank_api/priv/gettext/errors.pot
* creating bank_api/lib/bank_api/repo.ex
* creating bank_api/priv/repo/migrations/.formatter.exs
* creating bank_api/priv/repo/seeds.exs
* creating bank_api/test/support/data_case.ex

Fetch and install dependencies? [Yn] # <--- press Y or Enter here!
* running mix deps.get

We are almost there! The following steps are missing:

    $ cd bank_api

Then configure your database in config/dev.exs and run:

    $ mix ecto.create

Start your Phoenix app with:

    $ mix phx.server

You can also run your app inside IEx (Interactive Elixir) as:

    $ iex -S mix phx.server

Switching into the new generated folder, let’s create the database:

$ cd bank_api ; mix ecto.create

And start the Phoenix app server:

$ mix phx.server
[info] Running BankAPIWeb.Endpoint with cowboy 2.6.1 at http://localhost:4000

Now if you go to http://localhost:4000 you should see something like this in your browser:

Phoenix error message
Phoenix error message

This error is perfectly normal, since we don’t have any routes and we opted for no default HTML views!

Throughout the series, we’ll develop a simple HTTP API for a bank that will allow us to open and close accounts, deposit and withdraw funds and transfer them between accounts. A simplistic example, but we’ll be able to cover Aggregates, Commands, Events, Projections and Projectors, supervised Process Managers, Routers, Commanded middleware for auditing and validation, and of course testing for the API’s functionality.

Stay tuned for the next post!

Cover image credit: PIXNIO