In order to make web apps with Elixir, here’s a short primer on learning the language and major frameworks:
First, don’t just learn Elixir. You can and should learn Elixir and Phoenix at the same time. After getting a hang of Phoenix, jump into LiveView.
There is a learning curve to the ecosytem. It’s not particularly steep, but it is longer than a language like go but not as long as required by the Haskell or OCaml ecosystems.
Start with the official guide: https://elixir-lang.org/getting-started/introduction.html
For experience programmers, the syntax is heavily Ruby inspired. If you are familiar, it’s not a big leap.
Things to learn:
:identifier
or :key
or :date
["thing", "thing2", "kalamazoo"]
%{"abc" => 123, "xyz" => ""}
{1,2,3}
or {"key", value}
{:ok, success_value}
{:error, error_message}
[{:atom, "value"}, {:atom, "dup keys ok"}, {:ordered, "they remain orderd"}]
[shorthand: "notation", for: "keyword lists"]
def do_something(options)
all the following are equivalent:
do_something({:verbose, true}, {:debug, false})
do_something([verbose: true, debug: false])
do_something(verbose: true, debug: false)
do_something verbose: true, debug: false
~D[2021-02-03]
~r/foo|bar/
~T[23:00:07.0]
fn x, y -> x + y - z end
&(&1 + &2 - z))
function(arg1, arg2)
or sometimes you can omit the parentheses like so function arg1, arg2
.Immutable Everything
From erlang, you can’t change a data. You can bind (assign) a variable, and rebind it but you are binding a new thing. You never really change existing data.
The pipe operator |>
Pattern matching and guard clauses:
There is no return statement
The last expression is automatically returned. You can’t return early. This one will trip you up occasionally as you have to think about breaking up functions or using pattern matching, guard clauses, case statements or if statements instead of early return.
The Enum module
This one goes with the pipe operator as something you have to learn. It’s everywhere and it’s very “Elixiry” to have long chains of data transformation with Enums and pipes. In addition to the functional stalwarts of map, filter, reduce, there’s a ton of useful collection processing utilities in there. Eventually, you start thinking about transforming data instead of assigning and mutating variables.
https://hexdocs.pm/elixir/Enum.html https://elixir-lang.org/getting-started/enumerables-and-streams.html
Named Structs
They are kind of like objects if you squint hard enough. Really, they are maps with some type metadata baked in. You can pattern match against them and do other things with them. they look like this:
user = %User{name: "amattn", bday: ~D[2021-02-02]}
Erlang
You can call any erlang module.
https://elixir-lang.org/getting-started/erlang-libraries.html
mix
: build tool
hex
: package manager
hexdocs
: centralized documentation website
There’s still a lot to learn. I do recommend skimming thru every page of the getting started guide just to get a sense of what you don’t know yet:
In particular: - Module system, aliad, require, import - @attributes - OTP, processes, supervisors - GenServer - streams - [try catch, throw, after, rescue]: https://elixir-lang.org/getting-started/try-catch-and-rescue.html - meta-programming (macros)
Phoenix is an opinionated framework with quite a bit of magic to it. You can strongly feel the Rails influence. Paying attention to directory structure and naming conventions is much more important than in other web app frameworks. Like the entire Elixir ecosystem, this means there is a learning curve, but great velocity gains to be had once you get used to it.
The official guide is quite well written.
You should read the whole thing but start with the request life-cycle guide and then go back and read all the others.
Ecto is the Phoenix ORM (Technically it’s not an ORM, but it certainly covers much of the featureset of an ORM. Read more here). It works best with Postgres but the major databases vendors are all supported.
The official docs are well written: https://hexdocs.pm/ecto/Ecto.html
A good way to play around with Ecto is to try out the mix phx.gen
scaffold generators:
mix phx.gen.html
mix phx.gen.json
mix phx.gen.context
mix phx.gen.schema
phx.gen.html|json
create the context, schema as well as the controllers, view, templates, etc. the html variant in particular is a great example of seeing how ecto ties into phoenix and how changesets work at the data layer as well as in the UI.
phx.gen.context
will simply create the context and schema while phx.gen.schema
will only create the schema.
Also the phx.gen.auth project is an excellent example of of a vanilla but production ready auth setup with canonical Ecto usage.
mix mix phx.gen.auth Accounts User users
Some concepts:
Again, some of the best example code is the scaffolding:
mix phx.gen.live Blog Posts post title:string content:string publish:utc_datetime
And I can’t recommend enough Pragmatic Studio’s LiveView Starter and Pro Courses. In particular, From the free starter course: lessons 3 and 4 are the best intro to what LiveView is and lessons 18 and 19 on the two tupes of LiveComponents (stateful and stateless).
Once you get the basics down, There are two great non-trivial projects you can look at for advanced usage:
I wrote an overview about deploying to a cloud instance here:
https://amattn.com/p/deploying_elixir_phoenix_webapps_to_the_cloud_with_releases.html
Also checkout the #deployment channel in the Elixir slack community.
Docs:
Communities:
Newsletter:
Free stuff:
Stuff you have to pay for but is worth it: