The past decade has seen a swarm of new languages and technologies merge. Some have flourished with major companies backing them, like GO from Google, while others have slowly seen a drop in their popularity. With so many choices in the world, evaluating a new language and what merits they contain becomes of vital importance. Which brings us to Elixir, a language that has boasted about its overall performance, its scalability and stability thanks to its parent language, Erlang.
Starter project needs
Coming from a professional Ruby background, I was really intrigued by Elixir’s promises. And with frameworks such as Phoenix which has been praised for its sleek design without the underlying magic that you see in Rails. I had some incentive to begin my exploration to developed a few starter projects that could cover most web application needs.
To cover the grounds of what most web applications do, I needed to develop something that had the following tasks
- Multi-level model associations
- Image processing
To accomplish this, I decided to make a forum project. A perfect start that requires all the the tasks listed above.
- The user is required to authenticate using Github’s OAuth system.
- The user can create categories.
- The user can create thread’s inside of categories.
- Then the user can post inside of a thread.
- Finally, we allow the user to upload an avatar, that is processed with imagemagick then uploaded to an S3 bucket for displaying.
As a Rails developer, I’ve grown quite accustomed to Active Record and all the little bells and whistles that an object oriented program (OOP) provides. Luckily the community of Elixir has a solution for dealing with database querying called Ecto. Ecto is a highly customizable, yet super barebones solution for managing your database.
Here’s an example of what querying in Active Record Vs. Ecto looks like.
Immediately we can start to see some pretty stark differences. In the Rails example, Active Record is inherited into the User model, simplifying the query command. Whereas Elixir doesn’t have the concepts of OOP and from what we see is a very SQL query like experience. Out of the box, Ecto isn’t geared to morph into functions that help manage your model records. There are however quarks to this when introducing meta-programming, but that goes beyond the scope of this blog :).
Querying with Ecto
Let’s take a moment to look at an example of querying all posts for a given user between Rails and Ecto.
With Rails it’s really simple:
Rails doesn’t require the object to be joined in any fashion to access the user’s posts. While there might be cases of N+1 performance issues, it still doesn’t prevent it.
With Elixir there’s a little bit more work to be done.
While it is more work to effectively accomplish the same task, the question that remains is, Is it bad? In short no, its not. The biggest obstacle between switching between Ruby and Elixir is the idea of modular design. Good design patterns are long held as the holy grail of good programming behavior. Elixir and Ecto isn’t designed to do magic behind the scenes. It forces its developers to think how and why they are implementing features. This reason alone among many others, is why querying with Ecto can offer a much faster response time than that of Active Record. We run proper joins where we need them, retrieve only the data we care about, and not the stuff we’ll never use.
Complex querying with Ecto
For the final example I want to present what a complex query looks like in Ecto. The end goal is to select the latest thread for all categories by the ordering of a thread’s post creation date. All while returning the pre-loaded user data. This is a fairly typical query you’ll see when viewing a forum that shows the latest post for a given topic. (https://www.vbulletin.com/forum/)
Essentially our schema looks like this:
A Category has many Threads
A Thread belongs to a Category
A Thread has many Posts
A Post belongs to A Thread
A Post belongs to A User
A User has many Posts
To accomplish our goal, we need to break this down into a few nested queries that our database can understand.
- We need to order all post by their creation date and distinctively select posts based on their parent’s thread id.
- From there we join thread’s and post together. While maintaining the ordering the post’s came in.
- Since we only want one thread for every category, we need to distinctively select threads by their parent’s category id.
- Finally we join both thread and categories together to return a latest thread and post for each topic.
Here is what it looks like when this is all put together:
Elixir is a growing language and with the aid of Ecto, it can now start to become more and more mainstream. Both myself and the rest of the developers here at Elevator Up are really excited for the future of Elixir. We see it as a very scalable and stable platform that plenty of business could leverage for their next upcoming projects.
Forum Source: https://github.com/GeorgeKaraszi/MockForum
~George Karaszi, Software Developer
Originally published at blog.elevatorup.com.