Playing with Elixir/Phoenix
Anton Sakharov, CTO @ MLSDev
Elixir / Phoenix
This talk is not about
Elixir syntax or Phoenix cool features
The best way to master new technology
or framework is
to develop something simple but
not useless
* IMHO
Internal company website: Quote Pad
● Post quotes
● View quotes (latest / best)
● Vote for quotes (like / dislike)
● Email subscription to new quotes
Features
Old Quote Pad
● Written in 2012 by iOS developer in order to learn Ruby on Rails
● Rails 3.2.6
● SQLite in production ¯_(ツ)_/¯
● Email/password authentication using Devise gem
● Non-responsive UI
● No moderation functionality
● No admin area/dashboard
New Quote Pad
● Elixir/Phoenix
● Authentication via Google Apps / G Suite / whatever they name it tomorrow
● Amazon RDS / PostgreSQL
● UI facelift, make it responsive
● Moderation, admin. dashboard, blah-blah-blah...
● Migrate data/content
Learning curve
1. Elixir
2. Phoenix
3. Libraries
4. Deployment
5. …
6. PROFIT!!!
First steps
and things to avoid
Do not jump to Phoenix
straight away
Learn Elixir first
https://elixir-lang.org -> GUIDES
Do not learn Elixir and
Phoenix by tutorials and
videos only
1. You'll stay a Script Kiddie
2. Tutorials are probably outdated
This book is about Phoenix 1.2.
Current Phoenix is 1.3; 1.4 is about to be released
http://phoenixframework.org/
Before you go on ...
Must-read documentation
● Elixir guides (mentioned earlier)
● Phoenix guides and docs
● Plug (Rack / Middleware in Rails world)
● Ecto (ActiveRecord in Rails world)
https://hexdocs.pm
Pitfalls
● Do Elixir stuff non-Elixir way
● Do Phoenix stuff Rails-way
● Tend to OOP
● Erlang OTP gives you a lot out of the box, keep it in mind
● On the other hand, there are not that many
production-ready packages yet (like RubyGems)
Pitfalls
Do Elixir stuff non-Elixir way
Non-Elixir:
list = Enum.map(1..100_000, &(&1 * 3))
list = Enum.filter(list, odd?)
list = Enum.sum(list)
Elixir:
list =
1..100_000
|> Enum.map(&(&1 * 3))
|> Enum.filter(odd?)
|> Enum.sum
Elixir:
def sum_list([head | tail], acc) do
sum_list(tail, head + acc)
end
def sum_list([], acc) do
acc
end
Non-Elixir:
sum = 0;
for (i=0; i<sizeof(array); i++)
sum += array[i]
Do Elixir stuff non-Elixir way
Do Phoenix stuff kind of Rails-way
defmodule User do
schema "users" do
# ...
field :quote_count, :integer, virtual: true
end
# ...
end
# …
def list_users(user, params) do
page = User |> Repo.paginate(params)
# Don't do this ;)
%{page | entries: Enum.map(page,
fn u -> %User{u | quote_count: Quotes.user_quote_count(u)} end)}
end
OOP habits
user.update(%{role: "admin"}) # this is not Elixir ;)
Users.update(user, %{role: "admin"}) # this is!
What about background jobs ?
Not too many production-ready stuff available yet
● from simple things like URL validators
● to advanced like Devise for Rails
Bodyguard
Authorize plug
Data migration
● dump SQLite database: `sqlite3 dbname.sqlite3 .dump > dump.sql`
● remove `AUTOINCREMENT`
● varchar(255) -> `CHARACTER VARYING(255)`
● datetime -> `TIMESTAMP WITHOUT TIME ZONE`
● ` (backtick) -> ' (single quote)
● '' (empty string) -> `NULL` for empty date/time
● ...
Deployment
● Distillery
● edeliver
● .env
● nginx in reverse proxy mode
● SSL certificate
● Docker
● AWS ECS
● …
● WAIT!
rel/config.exs
Deployment pitfalls
● Erlang binaries: Mac OS X vs Linux
● Erlang versions: brew vs apt-get
● t2.micro (1 GB RAM) fails to build Erlang from source:
virtual memory exhausted
● it takes sooooo long to build Erlang from source…
Deployment pitfalls
DEMO
Links
https://elixir-lang.org/
http://www.phoenixframework.org/
https://github.com/h4cc/awesome-elixir/
https://hex.pm
https://hexdocs.pm/
https://github.com/mlsdev/
Any questions?
Thank you!

Playing with Elixir/Phoenix