Blog

We write about Ember.js, Ruby on Rails as well as Elixir and Phoenix.

Back End Development

Phoenix Fundamentals

Phoenix makes building robust, high-performance web applications easier and more fun than you ever thought possible.

Combining popular conventions formed in popular projects like Ruby on Rails with the robustness of Elixir and the BEAM make it an excellent choice for a broad range of applications.

1
Module 1 Duration: 300 minutes

1 — Request, Response

A Phoenix app can basically be boiled down to a function that receives a HTTP request, and returns a response. We’ll begin with this premise, and start to understand the important parts involved in this process.

Agenda
Request, Response Duration: 15 minutes
9:00
Welcome & Setup

We’ll set our sights on some specific goals for our Phoenix learning adventure, and ensure that everyone has what they need to get the most out of the training.

Request, Response Duration: 30 minutes
9:15
Endpoint & Routing

Requests enter your app through an Endpoint, which your app usually have just one. We’ll look at this chain of Elixir Plugs, which ends at the Router, the module ultimately responsible for delegating request-handling to an appropriate Controller.

Request, Response Duration: 30 minutes
9:45
Plugs & Pipelines

Plugs are at the core of Phoenix and a relatively simple concept: plugs accept a connection as an argument, and return a slightly-modified connection.

Once we chain a few plugs together, it’s easy to see how basic building blocks assemble into a complete application.

Request, Response Duration: 15 minutes
10:15
EXERCISE: Routing to the Pages controller

Your new Phoenix project comes with a PagesController that renders a landing page you can see at localhost:4000. See if you can infer from how files are organized in the templates folder, how you can make a static HTML page reachable at ` localhost:4000/my_page.

Request, Response Duration: 30 minutes
10:30
EXERCISE: Hating on a Content-Type

Apparently SOAP is out of style. Let’s return a discriminatory error message if we receive any request that has a SOAP content type.

SOAP is for washing up, not for APIs.

Build a Plug that interrupts the pipeline (returning a HTTP error for an incoming request) if we ever receive a request for a SOAP XML document (Content-Type: application/soap+xml)

Request, Response Duration: 30 minutes
11:00
The Controller Responds

Now that we understand how to leverage Phoenix’s routing layer, let’s take a closer look at Controllers – the modules ultimately responsible for responding to a request.

Request, Response Duration: 30 minutes
11:30
EXERCISE: Marco, Polo

In the PagesController, create a new action that returns a welcome message for a name. The router should delegate responsibility to this action for GET requests to http://localhost:4000/welcome_me/<name> and http://localhost:4000/welcome_me?name=<name>.

If the Accept header for the incoming request indicates that the client wants HTML, they should receive a reasonable HTML response, otherwise, they should receive JSON.

Request, Response Duration: 30 minutes
12:00
Views & Templates

In contrast to other web frameworks, Phoenix’s view layer is exceedingly easy to understand and use. Judging by how easy it is to keep views simple, performant, and easy to manage, It’s clear that the hard-learned lessons from older frameworks have paid off.

Request, Response Duration: 30 minutes
12:30
EXERCISE: Revise our HTML response

Let’s revise our previous approach to HTML rendering for our welcome endpoints, so that they take advantage of Phoenix’s view layer. Make sure to use assigns to make values available to views.

Request, Response Duration: 60 minutes
13:00
Lunch

Break for Lunch

2
Module 2 Duration: 180 minutes

2 — Managing Data

Data is an integral part of virtually any web application, and a great persistence library make a huge difference in performance and maintainability.

Thankfully, the Elixir ecosystem has us covered in spades. Ecto is a thin layer of functions that allow us to build composable queries, validate fields, and seamlessly transform records between our DB and application representations.

Agenda
Managing Data Duration: 20 minutes
14:00
Intro to Ecto

Heavy persistence libraries like ActiveRecord offer convenience, but often become performance bottlenecks. We could make every DB query explicitly, but then we’re trading in all of our ergonomics for performance.

Ecto manages to strike an enjoyable balance, where we are asked to be deliberate about the records we fetch from a database but (most of the time) aren’t dragged into the world of writing SQL queries explicitly.

You’ll be amazed at how much we can do with just simple functions, and will never look at other persistence frameworks quite the same way again.

Managing Data Duration: 40 minutes
14:20
Schema & Managing Migrations

If you’ve never used code to manage changes to your database schema, you’re missing out. Migrations allow us to change our schema in (ideally) reversible steps, so we can apply and un-apply a set of changes while building features.

Even if you’ve seen migrations before, there are some useful things to know about how they work with Ecto, and in particular, Postgres. We’ll look specifically at:

  • Postgres array and jsonb column types
  • Changing column types, while remaining backwards compatible
Managing Data Duration: 30 minutes
15:00
EXERCISE: Ecto Models

Make Ecto models to match the provided specifications (and successive changes to specifications). Ensure all of your DB migrations are reversible, and backwards compatible.

Managing Data Duration: 45 minutes
15:30
Cracking Changesets

This is one of my favorite parts about Ecto, and one of the parts you’ll be most often working with. In contrast to other persistence libraries, the concept of the shape of a record (schema) and the logic for checking the validity of values (validations) are decoupled. There are some incredibly exciting consequences of this design decision.

Ecto ships with a bunch of validations, and because it’s so quick and easy, we’ll write a few of our own.

Managing Data Duration: 30 minutes
16:15
EXERCISE: Validating for Password Complexity

Create a new field on our User model that validates the password field, ensuring that:

  • it’s not empty
  • it has a minimum length of 8 characters
  • it includes an upper-case letter, symbol, lower case letter, and a number
  • it doesn’t include more than two successive letters or numbers like abc or 123

Failing any of this validation should be met with an appropriately descriptive error message.

Managing Data Duration: 15 minutes
16:45
Recap & Wrap Up

We’ll recap the topics we’ve covered today, answer any remaining questions, and preview the topics we’ll cover tomorrow.

3
Module 3 Duration: 155 minutes

3 — Testing

Testing ergonomics is perhaps the most impactful factor in determining whether writing tests is an enjoyable part of day-to-day development, or an annoying slog that’s neglected until problems arise.

In this area, Phoenix does not disappoint. We’ll focus on several useful patterns for unit and acceptance testing, with the aim of making tests quick, easy, maintainiable and intuitive.

Agenda
Testing Duration: 15 minutes
9:00
Welcome Back

One more recap of what we learned yesterday, to get those fresh in everyone’s minds again, and a quick agenda of what we plan to do today.

Testing Duration: 30 minutes
9:15
Model Tests

When working with Ecto, you may notice that your model layer is much thinner than what you’re used to. Particularly if you’ve never used a functional language to build web applications, you may have to get used to your models being a collection of functions, rather than a factory for “record objects”. We’ll learn about ExUnit, the unit testing library that Phoenix ships with, and focus on a few common model testing needs:

  • Functions that return changesets
  • Validations that are run on said changesets
  • Special types of fields (i.e., virtual fields, fields with default values)
Testing Duration: 30 minutes
9:45
EXERCISE: User Model Tests

Write some user model tests, and most importantly, build tests around our password validation logic from yesterday.

Testing Duration: 30 minutes
10:15
Controller & View Tests

Sometimes we use Phoenix to render HTML, so we’ll look at how we can verify that both our controller and view layers (individually) are doing their job. Together, we’ll write some unit tests for the “welcome” pages we made yesterday.

Testing Duration: 20 minutes
10:45
JSON API Tests

Often we use Phoenix Controllers to render JSON. We’ll explore some built-in helpers that are well-suited for helping us write tests verifying that the JSON contains what we expect, and touch on a few libraries that make this even easier!

Testing Duration: 30 minutes
11:05
EXERCISE: JSON Tests
  1. Build some tests around the StatusControllers JSON endpoints, protecting it from regression
  2. Build a test asserting that our anti-SOAP Plug works as intended
4
Module 4 Duration: 150 minutes

4 — Real Time

One of the places where Elixir and Phoenix leave the competition in the dust is support for soft real time programming. The ability to keep a lightweight Elixir process running for the duration of a user’s time in our app, and holding some small amount of state, makes our world far simpler for certain things than it otherwise would be.

Agenda
Real Time Duration: 35 minutes
11:35
Channel Basics

Phoenix Channels are a first class citizen in the framework, on equal footing with Controllers. It shows! You’ll be amazed at how easy it is to start adding real-time features to your apps, where we push data from server to client.

Development best practices are increasingly moving in a functional and “stateless” direction, but Elixir Processes are a place where small pieces of state can be safely held and used. We’ll explore how powerful this idea is, in the context of Phoenix channels.

Real Time Duration: 30 minutes
12:10
Managing Channel Complexity

While you may have contributed to a REST API project that had 10 endpoints (each handling 1-4 HTTP verbs), it’s less likely that you have experience working with a long-lived web socket connection operating on the same scale of complexity. It’s important to remember that this is API surface, and because it’s often stateful instead of stateless, keeping organized is even more important.

Real Time Duration: 35 minutes
12:40
EXERCISE: Push Notifications

We have a need to instruct consumers of our API to render a notification on their screen. Broadcast a notification object to all users subscribed to the notifications:all channel, consisting of a type and a body.

Real Time Duration: 50 minutes
13:15
Lunch

Break for Lunch

5
Module 5 Duration: 165 minutes

5 — Users & Authentication

Nearly every app we build these days requires some sort of authentication, and probably a user account to go along with it. Even if your app is an oddball and doesn’t need this, user accounts provide us with a well-understood set of use cases that will serve as an excellent case study.

Let’s put some of our newfound Phoenix knowledge into practice as we implement a secure user account feature set. The goal will be to reduce explicit management of authorization & authentication on a per-resource basis as much as possible.

Agenda
Users & Authentication Duration: 55 minutes
14:05
EXERCISE: User Registration

Creating new users will serve to highlight a few concepts at the model layer

  • Server-side validation, including writing our own validator
  • Safely handling passwords
  • Keeping slightly different changeset-generating functions organized

We’ll also have an opportunity to start defining routes that require a user to be authenticated, and routes that don’t.

Users & Authentication Duration: 45 minutes
15:00
EXERCISE: Login/Logout

For our purposes, we’ll use a JSON Web Token (JWT) and the OAuth 2 password grant standard, as a mechanism and vehicle for authentication. You will be provided with a client-side app that will talk to our Phoenix, via JSON.

We’ll validate a user’s credentials in a way that’s not incredibly sensitive to timing or brute force attacks, and then assemble our little piece of session state (the JWT) before encrypting it and handing it back to the client.

Users & Authentication Duration: 45 minutes
15:45
Exercise: User Roles

We often have a concept of roles (or an equivalent concept masquerading as other flags/fields) built on top of our authentication. We’ll add roles to our JWT, and design a plug that will raise an error if a user attempts to access a controller action without having the required roles.

Users & Authentication Duration: 20 minutes
16:30
Wrap Up & Recap

We’ll recap everything we’ve covered in this training, and finish by providing a rich set of resources for further learning.

Get your team trained!