We love Ruby. We have enough experience with Ruby and web software development. But something that we love even more is being up to date. We are always trying new libraries, frameworks, designs and languages too. We like to get our own experience, contribute to as many open source projects we can. This is something that we enjoy, individually and as a team. It is part of the company’s culture.
Personally I like to start with new languages, see how they evolve, how the community grows and how they tackle the old and the new challenges. I found Elixir to be a programming language which will play an important role in the future, where parallel computing is a bottleneck for Ruby.
Lets take a look to the tools that Elixir offers.
What is Elixir?
If syntax wasn’t important, then we’d all still be using Roman numerals
Joe Armstrong - “The mess we’re in”
Concurrent programming is known to be difficult, and there’s a performance penalty to pay when you create lots of processes. Elixir doesn’t have these issues, thanks to the architecture of the Erlang VM on which it runs. However, we will leave that subject for future posts and focus on our first steps using Elixir.
For better understanding, let’s build a dummy application which parses an external API response.
Use omdb API to search movies by title, parse the JSON response and show the relevant movie’s attributes with a nice view.
To accomplish this, we are going to use the Phoenix framework which is also maintained by the creators of Elixir.
I’m using OS X, so the installation is very straightforward
When you install Elixir, besides getting the
executables, you also get an executable Elixir script named
mix is a build tool which provides tasks for creating, compiling, testing your
application, managing its dependencies and much more.
And finally, the Phoenix framework
Creating the application
We can run
mix phoenix.new from any directory in order to bootstrap our Phoenix
application. Phoenix will accept either an absolute or relative path for the
directory of our new project. Assuming that the name of our application is
random_movies, either of these will work:
In Phoenix, Ecto is a database wrapper and language integrated query based in the Repository pattern which IMHO is way better than ActiveRecord (the most common pattern used in Ruby web applications).
Given our application will fetch the data from an external API, we don’t need the
persistence layer, so we can pass
--no-ecto to opt out of Ecto:
For those who come from Rails or MVC-based applications they won’t find anything new because Phoenix uses the MVC pattern too.
Controllers and Views
Phoenix controllers act as intermediary modules. Their functions - called actions - are invoked from the router in response to HTTP requests.
Every application created by
mix phoenix.new will have:
- A controller, the
- A view, the
- A template,
Phoenix assumes a strong naming convention from controllers to views to the
templates they render. The
PageController requires a
PageView to render
templates in the
Phoenix views have two main jobs:
- Rendering templates (this includes layouts).
- Providing functions which take raw data and make it easier for templates to consume.
For templates, Phoenix uses EEx which is part of Elixir. EEx is quite similar to ERB in Ruby.
As I mentioned before, we want to display the movie poster and most relevant attributes.
Let’s assume the controller give us a Map
@movie with the attributes of the movie we want to show.
Our template should look something like this:
For simplicity, we will overwrite the
web/templates/page/index.html.eex file with this content.
Now, we need to actually send the movie
Map from the controller.
page_controller.ex file and edit the
index function like this:
mix phoenix.server to start your server, go to localhost:4000
and you will see the following screen:
Congratulations! You have an Elixir application running on your machine! It was pretty simple, wasn’t it?
I know, we cheated, there is no API parsing. But I didn’t tell you we had finished.
So far, it looks like a Rails application with a few small differences. It is time to get our hands dirty.
When you deal with an external API, the best practice is to have a wrapper to contain the logic associated in one place. That is what we are going to build.
When compiling, Elixir will look for source files in our
lib directory, as long
as the file extensions are correct (standard is *.ex for files meant for compilation),
and create the corresponding BEAM bytecode files.
We’re going to follow the convention and place our
Omdb module file in
This module is responsible of:
- fetching the OMDB API
- handling the response
- converting the JSON object into a Map
Elixir does not provide an HTTP client on its toolset, but there is a library which suits perfectly for our needs: httpoison.
Adding a dependency to our project is as simple as adding the library in the
deps list in the
mix.exs file. It should look something like this:
In order to run the
httpoison application when our server starts, just add
:httpoison at the end of the
applications list in the same file.
Now we are ready to tackle the three responsibilities of the
1. Fetching the OMDB API
We will receive the title to search from the controller, but only the title. We want to convert that string into a valid API resource.
According to the omdb documentation, we need to do a simple GET to the URL.
If you noticed, this looks exactly as a ruby method, except for the
Although it is completely valid Elixir code, this is not the best way to write it.
The following snippet uses a better syntax that Elixir provides, using the pipe operator.
|> symbol used in the snippet above is the pipe operator: it simply takes the
output from the expression on its left side and passes it as the input to the
function call on its right side. It’s similar to the Unix
Its purpose is to highlight the flow of data being transformed by a series of functions.
2. Handling JSON response
To tackle the second step, I need to introduce you a not-so-new concept: Pattern Matching
Pattern Matching allows developers to easily destructure data types such as tuples and lists. It is one of the foundations of recursion in Elixir and applies to other types as well, like maps and binaries. Basically it lets you write different forms of a function that code can match against, and the compiler will invoke the first definition that matches the pattern.
That being said, we want to apply Pattern Matching on the response.
HTTPoison.get/2 return value is a tuple of two elements.
The first one is an
atom (known as symbols in rubyland) representing the
status of the call. This is really helpful to identify a failed call using
pattern matching. This will be our first pattern matching.
defp is a keyword to define private functions.
The code above handles two different return values.
HTTPoison.get/2 returns an error, Elixir will run the first definition,
otherwise the second one.
In case we get a successful response from the API, we are able to pattern match on the status code, body, or any other part of the response making the code more readable and declarative, like the following snippet:
Unfortunately, the OMDB API responses are
200 even when the element is not found.
That is why we can’t use the pattern matching on the
status_code, instead we are
going to match the body to decide if it was found or not.
On the other hand, on error responses, we want to return a tuple with the atom
:error and the reason.
Wrapping up, we get
3. Converting JSON to Movie Struct
Finally we got here! We hit the API, we got a successful result and we have a valid JSON waiting to be parsed and displayed in our front page.
This is one of the most straightforward steps, thanks to Phoenix. A library called poison is included in the framework and it allows us to encode and decode JSON strings.
That would be enough. However, I would like to go one step further and create
Movie which declares the specific attributes we want to keep.
At the beginning of the article I told you we are not going to use ecto,
instead we will define a struct to represent a movie.
To achieve this, we create a new file
web/models/movie.ex and copy the following
code in it:
Now we are ready to decode the JSON response and convert it into a Movie.
Given this is a common use case,
poison introduces an option to do it.
When we put all these functions together, we get our API wrapper complete!
I extracted the user_agent into a variable to improve the readability of the code.
There is only one thing left to do: take the argument from the URL and call the API.
web/router.ex file, replace
get "/", PageController, :index
with this other line, which basically adds a name to the parameter
get "/:query", PageController, :index
Back in the
PageController, we need to update the index action to accept a parameter
and to call the Omdb wrapper instead of hardcoding a movie.
But at this time, you will find that you know how to do it… pattern matching!
Finally, we get a title to search from the URL, we call the API, parse the response
and return a movie, or an error if it wasn’t found. To reflect this in our outdated
template, we can add a simple
if statement and restart our server to see it working.
Use the application
Play around with the dummy application we built. Here is a list of my favorite movies if you are lazy and don’t want to look out for movies:
If you just want to review the code, or download and run the server immediately here is the source code.