Skip to content

Repository files navigation

programming-phoenix

About

This repository is a workspace for working through Programming Phoenix (1.4), split into three subprojects — hello/, rumbl/, and rumbl_umbrella/ — one per stage of the book, as described below.

The book was written in 2019, and its exact dependency versions are by now outdated — current releases of Elixir, Phoenix, Ecto, and their supporting libraries have moved well past what it was written against, and following it verbatim against today's toolchain runs into breakage at nearly every step. Despite that, the book remains genuinely valuable: its structure, and the way it walks through building a real Phoenix + OTP application end to end (contexts, channels, an OTP supervision tree, testing strategy), still holds up as a model for how this kind of application should be put together. That's the reason for this repository's first order of business — before writing any application code — being to reconstruct a toolchain close to what existed in 2019 (.tool-versions below), so the book's own examples run as originally written rather than fighting version drift the whole way through.

The intent is for this repository to work as a companion to the book: a place to keep the code, the runtime steps, and the notes on wherever reality (a changed API, a library that no longer behaves the same way) diverged from the text — for anyone else treating Programming Phoenix as I do, as essential reading for real-world Elixir + Phoenix

Toolchain

Versions pinned in .tool-versions:

  • Erlang 22.3.4.27
  • Elixir 1.9.4-otp-22
  • Node.js 12.22.12

Projects

  • hello/ — the "It's ALIVE!" skeleton app from the book's early chapters (Chapter 2).
  • rumbl/ — the single-app rumbl build-up (Chapters 3–10): controllers, Ecto, auth, video CRUD, channels.
  • rumbl_umbrella/rumbl restructured into an umbrella app (Chapter 11 onward): the info_sys OTP information system, WolframAlpha backend, and channel/OTP testing (Chapters 12–13).

Environment setup (asdf install)

On Fedora 44 (GCC 16 / OpenSSL 3.5), Erlang 22 fails to build with a plain asdf install because:

  1. GCC 16 defaults to C23, where false is a reserved word, which breaks ttsl_drv.c.
  2. OpenSSL 3.5 removed openssl/engine.h, required by OTP 22's crypto module, and Fedora 44 has no openssl1.1 compatibility package.

1. Build OpenSSL 1.1.1 into a local prefix (one-time)

mkdir -p ~/local/src
cd ~/local/src
curl -O https://www.openssl.org/source/openssl-1.1.1w.tar.gz
tar xzf openssl-1.1.1w.tar.gz
cd openssl-1.1.1w
./config --prefix="$HOME/local/openssl-1.1.1w" shared
make -j"$(nproc)"
make install_sw install_ssldirs

2. Install the versions pinned in .tool-versions

CFLAGS="-O2 -g -std=gnu17" \
KERL_CONFIGURE_OPTIONS="--disable-fop --with-ssl=$HOME/local/openssl-1.1.1w" \
asdf install

This installs erlang, elixir, and nodejs as defined in .tool-versions. The flags only affect the Erlang build; Elixir and Node ignore them harmlessly.

crypto.so ends up linked against the local OpenSSL via an embedded rpath, so no persistent LD_LIBRARY_PATH is needed.

3. Install the matching phx_new archive

mix archive.install hex phx_new grabs the latest release, which requires a newer Elixir than the one pinned here. Install a version compatible with Elixir 1.9.4 instead:

mix archive.install hex phx_new 1.4.17 --force
phx_new requires Elixir
1.8.x ~> 1.17
1.6.x ~> 1.12
1.5.x ~> 1.7
1.4.x ~> 1.5 (works with 1.9.4)

Check the installed version with:

mix phx.new -v

Using :observer

:observer.start() doesn't work out of the box on this Erlang 22 build — Fedora 44's system wxWidgets (3.2.9) is too new for OTP 22's wx bindings to link against. See OBSERVER.md for the fix (building wxWidgets 3.0.5 into an isolated prefix and rebuilding Erlang against it).

Postgres

docker compose up -d

Starts postgres:18.1 on port 5432 (user/password postgres), used by the book's exercises.

Generating a new app

mix phx.new hello

Pin dependency versions before mix ecto.create

mix.exs generated by phx_new 1.4.17 leaves several deps unpinned (ecto_sql, postgrex, plug_cowboy, etc.). There's no command that does this automatically — mix deps.get doesn't consider Elixir/OTP compatibility when resolving versions, so it fetches today's latest releases, which require Elixir 1.15+ and in some cases Erlang syntax OTP 22 can't even compile (e.g. cowlib's HTTP/3 module). You have to edit mix.exs by hand and replace the deps block with versions from the Elixir 1.9 / OTP 22 era:

defp deps do
  [
    {:phoenix, "~> 1.4.17"},
    {:phoenix_pubsub, "~> 1.1"},
    {:phoenix_ecto, "~> 4.4.0"},
    {:ecto_sql, "~> 3.7.2"},
    {:postgrex, "~> 0.15.13"},
    {:phoenix_html, "~> 2.11"},
    {:phoenix_live_reload, "~> 1.2", only: :dev},
    {:gettext, "~> 0.19.1"},
    {:jason, "~> 1.0"},
    {:plug_cowboy, "~> 2.5.2"},
    {:cowboy, "~> 2.8.0"},
    {:cowlib, "~> 2.9.1"},
    {:ranch, "~> 1.7.1"},
    {:plug, "~> 1.13.6"},
    {:plug_crypto, "~> 1.2.5"},
    {:db_connection, "~> 2.7.0"},
    {:decimal, "~> 2.3.0"},
    {:mime, "~> 1.6.0"},
    {:file_system, "~> 1.0.0"}
  ]
end

Then reset the lock file and dependencies before fetching again:

rm -f mix.lock
rm -rf deps _build
mix deps.get
mix compile

Create the database and start the server

mix ecto.create
mix phx.server

About

Workspace for working through the Programming Phoenix (2019) book with a period-accurate toolchain (Erlang 22, Elixir 1.9.4, Node 12). Three subprojects — hello, rumbl, rumbl_umbrella — follow the book chapter by chapter, with docs noting anywhere today's libraries diverge from the text.

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages