Playing with Phoenix Framework — Rails’ younger brother

Michał `fazibear` Kalbarczyk
EL Passion Blog
Published in
4 min readJul 28, 2015

Have you heard about Phoenix? It’s a new web framework written in Elixir language. And Elixir itself is a Ruby inspired language that runs on Erlang Virtual Machine. Yes, a lot of ties and references, but we are all one big family here, aren’t we?

Let’s see how closely related are Phoenix and Rails. We’ll do it all from scratch on OS X, with some help from Homebrew package manager.

The Environment

We’ll start with installing both languages that the frameworks rely on. Just like Ruby, Elixir already has several version managers to choose from, like exenv and kiex. But we won’t use them for the sake of simplicity.

Ruby installation:

$ brew install ruby

Elixir installation:

$ brew install elixir

Next thing we need is a package manager. Just like Ruby has its Gems, Elixir’s package manager is called Hex. Equivalent for Ruby’s Rake is Elixir’s Mix. Hex + Mix combined give us Ruby’s Bundler dependencies management functionality.

So we use Mix task to install Hex package manager:

$ mix local.hex

The Foundation

We don’t do it often, so let’s recall how to install the Rails framework:

$ gem install rails

Phoenix framework installation is no harder:

$ mix archive install phoenix

We’re ready to create a new application. In Rails it’s nothing more than running everyone’s most beloved command:

$ rails new railsapp

The command created new app with its directory structure, and then Bundler downloaded and installed all dependencies.

Let’s see how Phoenix deals with the task:

$ mix phoenix.new phoenixapp

Wow! New application created, dependencies downloaded. Beautiful.

To test our sample application we have to start a web server.

A Rails server:

$ rails server

And Phoenix server:

$ mix phoenix.server

GET /hello_phoenix

Both frameworks are MVC based, so our main building blocks are models, views and controllers. Just like Rails, Phoenix has generators for those:

$ rails generate model

vs.

$ mix phoenix.gen.model

…but this is the easy way. I want to compare how to add the base features by hand, just to figure out the differences.

We’ll create sample page displaying a welcome message.

First things first, we’ll add a route for it. With Rails, we create new route by editing config/routes.rb file:

Rails.application.routes.draw do
get '/hello' => 'hello#index'
end

In Phoenix we have web/router.ex:

defmodule Phoenixapp.Router do
use Phoenixapp.Web, :router
...
scope "/", Phoenixapp do
pipe_through :browser # Use the default browser stack
get "/hello", HelloController, :index
end
end

Now, controllers time!

Within Rails app create app/controllers/hello_controller.rb file:

class HelloController < ApplicationController
def index
@text = 'Hello from Controller'
end
end

Within Phoenix create web/controllers/hello_controller.ex file:

defmodule Phoenixapp.HelloController do
use Phoenixapp.Web, :controller
def index(conn, _params) do
conn |> render "index.html", text: "Hello from Controller"
end
end

For the view we’ll use Rails’ erb and Elixir’s equivalent: eex.

For Rails we only need to create one file: app/views/hello/index.html.erb

<h1><%= @text %></h1>

Phoenix requires us to create a view module beside the template. It’s (more or less) like a view helper in Rails. It will sit in web/views/hello_view.ex:

defmodule Phoenixapp.HelloView do
use Phoenixapp.Web, :view
end

The accompanying template file will be web/templates/hello/index.html.eex:

<h1><%= @text %></h1>

Run servers once again. Go to the browser, type http://localhost:3000/hello for Rails and http://localhost:4000/hello for Phoenix. It just works! Do you have this feeling again?

Rising from the ashes

Who doesn’t like benchmarks and numbers? So here they are. Rails app was benchmarked with Passenger in production environment. Phoenix app was running with built-in cowboy server. The machine was Macbook Pro (2014, 2.6GHz i5, 8GB RAM).

Rails:

$ passenger start -e production
$ wrk -c100 -d10s http://localhost:3000/hello/
Running 10s test @ http://localhost:3000/hello/
2 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 143.47ms 21.31ms 295.32ms 91.25%
Req/Sec 346.55 39.50 440.00 74.50%
6927 requests in 10.05s, 8.96MB read
Requests/sec: 689.55
Transfer/sec: 0.89MB

Phoenix:

$ MIX_ENV=prod mix compile.protocols
$ MIX_ENV=prod PORT=4001 elixir -pa _build/prod/consolidated -S mix phoenix.server
$ wrk -c100 -d10s http://localhost:4001/hello/
Running 10s test @ http://localhost:4001/hello/
2 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 16.73ms 3.78ms 78.27ms 91.46%
Req/Sec 3.02k 290.98 3.58k 83.00%
60097 requests in 10.01s, 72.67MB read
Requests/sec: 6003.29
Transfer/sec: 7.26MB

Note that it is just a simple benchmark with empty controller. You have been warned :)

Oh, there is one important thing. Phoenix is Elixir, and Elixir is not Ruby. It looks a lot like Ruby but there are differences.

What else? In both frameworks’ controllers we have a params hash to manage url params. Error pages are very similar. There are more equalities. Asking for models? Rails has ActiveRecord, Phoenix has ecto. Both support various database drivers, tasks for managing the database and its schema through migrations. Both frameworks ship with built-in testing frameworks.

If you know Rails, you already are familiar with Phoenix. It is still very young, so you have the chance to be an early adopter, and I highly encourage you to play with it while it’s hot!

--

--