A beginner journey into Phoenix, Surface and Live View

My beginner journey into Elixir, Phoenix and Liveview started when reading about Changelog website and how fast it was reported to be by many developers.
This is where it all started

  asdf install
  mix archive.install hex phx_new
  mix phx.new hello
  mix ecto.create
  mix format
  mix test
  mix phx.gen.context
 etc ...

A few weeks past and I started to feel that this language / technology has something different.
Yes sure, the quantity or ressources available is way lower than others languages but the quality is greater and that’s what counts.
Let’s be honest, learning a new language is always a difficult task, this is maybe why the most experienced developers have a tendency not to switch to a different language.
Why would you go from 10+ experience in a language to only few months in Elixir ? this is the dilemma for many developers

In my own experience, starting with a small project that allows to cover the basics is the best way to go.

The hard part is to find the scale of the project, too small and you will miss some important concept and too big and you will more patch things that constructing them.

This is where I was browsing the companies currently using Elixir in general and found an article about Duffel Travel API.

Once again duffel.com -> Ressources -> Documentation

I immediately knew that this will be my first project with Phoenix Liveview.

Flytis.com is born, fully build with Elixir and Phoenix Framework from development to production with peace of mind as promised at start :slight_smile:

  • Elixir is a dynamic, functional language for building scalable and maintainable applications.

  • Phoenix Framework is a web development framework for the Elixir programming language.

  • Surface A server-side rendering component library for Phoenix Framework

  • Moon Design Moon Design System is a collection of reusable components build with Surface.
    A big shout out to their team, their project is amazing, a great learning ressource with hundred of full example of how to use the components in many different ways, not only using them but customizing them. Anyway you should give it a try because they use Dragon Ball Z naming for the color system

  • Gigalixir is a fully-featured, production-stable platform-as-a-service built just for Elixir.

  • Duffel API Sell travel,
    without the complexity. Any business can build flights and accommodation, purchase extras, manage bookings and more.

  • Ecto and Postgres for Database management with the use of Context, Changesets and Embebeded Shema.
    A special thank you to Benjamin Milde for his great article on Ecto Changests, it made using Changeset clear and easy

  • HTTPoison for managing the communication with Duffel API
    Thank you Changelog for their open source Craisin code to understand on how to use HTTPoison request, configuration and responses

  • Gettext and Cldr for translations and localization

  • Phoenix Auth for visitor and user authentication

  • UberAuth for user Google Authentication

  • ExMoney for Currencies and Price Cart management

  • MJML for responsive emails

  • Swoosh and GenSMTP for email sending

  • Pdf Generator for generating invoices and bookings

The Elixir and Phoenix environnement has been great to learn, without searching for solutions online, we can find the solutions by looking at the documentation directly.

Compared to other languages, there is way less updates and some Library seems not to be updated but this is good news. Why update something that works, let’s just add clear
improvements only, this seems to be the mentality

Lets take an examples : the Enum Library
There is more documentation than actually code, and the advises given are very clear.

  Filters the `enumerable`, i.e. returns only those elements
  for which `fun` returns a truthy value.

  See also `reject/2` which discards all elements where the
  function returns a truthy value.

  ## Examples

      iex> Enum.filter([1, 2, 3], fn x -> rem(x, 2) == 0 end)
      iex> Enum.filter(["apple", "pear", "banana"], fn fruit -> String.contains?(fruit, "a") end)
      ["apple", "pear", "banana"]
      iex> Enum.filter([4, 21, 24, 904], fn seconds -> seconds > 1000 end)

  Keep in mind that `filter` is not capable of filtering and
  transforming an element at the same time. If you would like
  to do so, consider using `flat_map/2`. For example, if you
  want to convert all strings that represent an integer and
  discard the invalid one in one pass:

      strings = ["1234", "abc", "12ab"]

      Enum.flat_map(strings, fn string ->
        case Integer.parse(string) do
          # transform to integer
          {int, _rest} -> [int]
          # skip the value
          :error -> []

For one function, we have a simple example, a related function (Enum.reject) and a common mistake (Enum.flat_map)

The error messages sound more like a friend giving a practical advise than a scientific solution

I personally used VScode with JakeBecker.elixir-ls extension and the autocomplete, shortcuts and functions lookup are great

Once again thank you to everyone involved in developing this amazing language with great comprehension of the developers needs: stability, informations, flexibility and efficienty

My main advise for anyone starting is to have your project tested in production from the beginning, this will allow you have a better understanding the construction of the app, the Live View cycle, latency and different configurations in general.
Some configuration especially may not work due to relative paths or dependencies that are not loaded in production when needed

My second advise is go over all the functions or the main Elixir library once at least. You may find functions and solutions to a problem you are solving differently.

For example when trying to display the error messages from a Ecto Changeset inside a popup instead of the default Error Tags under each field, I found myself sorting, filters, merging the errors messages. I then found out by looking at data_case.ex in the original test suite (Thank you again Phoenix team for your generators) , Ecto.Changeset.traverse_errors that just solve the problem

  def errors_on(changeset) do
    Ecto.Changeset.traverse_errors(changeset, fn {message, opts} ->
      Regex.replace(~r"%{(\w+)}", message, fn _, key ->
        opts |> Keyword.get(String.to_existing_atom(key), key) |> to_string()

If you have any questions regarding some integrations, libraries used or simply the code in general I will be more than happy to help.

Thank you for reading and happy coding