UP | HOME

Elixir, Phoenix, and GraphQL(Absinthe)

Long time ago, I play Elixir and write down an article about Phoenix. Time has passed, now I'm really working with Elixir XD. Today, I want to show how to set up a GraphQL server with Elixir/Phoenix stack, we will need a library called Absinthe. This article requires you already to know how to create Phoenix project, now, let's start.

After you have a Phoenix project, we need to add dependencies in mix.exs first:

defp deps do
  [
    # ...
    # GraphQL
    {:absinthe, "~> 1.4"},
    {:absinthe_plug, "~> 1.4"}
  ]
end

Then run mix deps.get. Before we create GraphQL schema, we need some data to interact with, you can run mix phx.gen.context Log Events events event_type:string message:string payload:text to get a model then run mix ecto.migrate to set up Database.

1. Query

Imagine the schema:

{
  events {
    id
    event_type
    message
    payload
    inserted_at
    updated_at
  }
}

We will create lib/xxx_web/schema/event.ex with the following content:

defmodule XxxWeb.Schema.DataTypes do
  use Absinthe.Schema.Notation

  object :event do
    field :id, :id
    field :event_type, :string
    field :message, :string
    field :payload, :string
  end
end

then create lib/xxx_web/schema.ex with the following content:

defmodule XxxWeb.Schema do
  use Absinthe.Schema

  import_types XxxWeb.Schema.DataTypes

  query do
    @desc "Get a list of events"
    field :events, list_of(:event) do
      resolve fn _parent, _args, _resolution ->
        {:ok, Xxx.Log.list_events()}
      end
    end
  end
end

In the project xxx, there will have a file lib/xxx_web/router.ex, now we have to modify it, delete the following code:

scope "/" do
  pipe_through :browser # Use the default browser stack

  get "/", PageController, :index
end

then add the following:

scope "/api" do
  pipe_through :api

  forward "/graphiql", Absinthe.Plug.GraphiQL, schema: XxxWeb.Schema
end

Finally, we can test it out, run iex mix -S phx.server to start the server. Now, connect to http://localhost:4000/api/graphiql with the browser, it will show a GraphQL playground you can play with it.

2. Mutation

We would like to create some data, how to do this? We still modify lib/xxx_web/schema.ex

defmodule XxxWeb.Schema do
  # ...
  mutation do
    @desc "Create a new event"
    field :create_event, :string do
      arg(:event_type, non_null(:string))
      arg(:message, :string)
      arg(:payload, :string)

      resolve fn _parent, params, _resolution ->
        case Xxx.Log.create_event(params) do
          {:ok, _} -> {:ok, "event created"}
          {:error, changeset} -> {:error, inspect(changeset.errors)}
        end
      end
    end
  end
end

Now you can use the following mutation to create an event:

mutation {
  createEvent(event_type: "Test", message: "Hello")
}

3. Summary

Now we know how to create queries and mutation with Absinthe, we don't cover how to add middleware, how to write unit test for our code. You will be able to get more information about those uncovered in document of Absinthe, have a nice day.

Date: 2021-07-06 Tue 00:00
Author: Lîm Tsú-thuàn