Basic but useful example of Elixir Protocols

August 11, 2019

Assuming you know the theory, in this example we’ll provide one login interface for different type of users.


Let’s start a new project:

mix new protdemo --sup


Structs

This example shows that passing different data types to our login function will trigger a different implementation.


We’ll have one struct per user role.

Create a new admin directory under lib/protdemo and put there a new file admin.ex:

# lib/protdemo/admin/admin.ex

defmodule Protdemo.Admin do
  defstruct [:admin_name, :password]

  def login(who), do: {:ok, who.admin_name <> " logged in as Admin"}
end


Create another directory called user under lib/protdemo and put there a new file user.ex:

# lib/protdemo/user/user.ex

defmodule Protdemo.User do
  defstruct [:user_name, :password]

  def login(who), do: {:ok, who.user_name <> " logged in as User"}
end


Protocols

The most important part now. Create a new file auth.ex under lib/protdemo

# lib/protdemo/auth.ex

defprotocol Protdemo.Auth do
  def login(creds)
end

defimpl Protdemo.Auth, for: Protdemo.Admin do
  def login(admin_creds), do: Protdemo.Admin.login(admin_creds)
end

defimpl Protdemo.Auth, for: Protdemo.User do
  def login(user_creds), do: Protdemo.User.login(user_creds)
end


Having different functions called based on the data type, we can implement completely different logic for admin and regular users.


The joining point is one function we’ll put to lib/protdemo.ex:

# lib/protdemo.ex

defmodule Protdemo do
  alias Protdemo.Auth

  def login(creds), do: Auth.login(creds)
end


Testing


# test/protdemo_test.exs

defmodule ProtdemoTest do
  use ExUnit.Case
  doctest Protdemo

  alias Protdemo.Admin
  alias Protdemo.Auth
  alias Protdemo.User

  test "Log in as User" do
    {:ok, "rafal logged in as User"} = Auth.login(%User{user_name: "rafal", password: "test"})
  end

  test "Log in as Admin" do
    {:ok, "rafal logged in as Admin"} = Auth.login(%Admin{admin_name: "rafal", password: "test"})
  end
end


I believe simple code examples are worth more than 1000 words.