Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
12
Help us understand the problem. What is going on with this article?
@ma2ge

Elixir で Absinthe を使って GraphQL に触れてみた

More than 3 years have passed since last update.

前々から気になっていた GraphQL を Elixir 言語で作られたライブラリの Absinthe を使って試してみました。軽く調べた感じでは Elixir で GraphQL するなら Absinthe 選ぶで良さそうです。まだベータですが本も出ています
この記事ではこちらにあるチュートリアルを元に query と mutation に触れるところまでやったことをメモします。
サンプルコードはこちら

前提

Erlang & Elixir & Phoenix あたりはインストールされている。

サンプルアプリのセットアップ

Phoenix Framework を使って土台となるアプリを作ります。

$ mix phx.new graphql_sample --no-brunch --no-html
$ cd graphql_sample

mix.exs の deps へ absinthe を追加します。

mix.exs
def deps do
  ...省略...
  {:absinthe_ecto, "~> 0.1.0"},
  {:absinthe_plug, "~> 1.3.0"}
end

absinthe を追加したのでライブラリを取得して DB まで作ります。

$ mix deps.get
$ mix ecto.create

データモデルのセットアップ

GraphQL でクエリをかけたり、データ操作をするためにモデルをセットアップします。
シンプルに links というテーブルを作るだけです。

$ mix phx.gen.context News Link links url:string description:text

seed 用のデータを作ります。

priv/repo/seeds.ex
alias GraphqlSample.News.Link
alias GraphqlSample.Repo

%Link{url: "http://graphql.org/", description: "The Best Query Language"} |> Repo.insert!
%Link{url: "http://dev.apollodata.com/", description: "Awesome GraphQL Client"} |> Repo.insert!

seed データを DB へ反映します。

$ mix ecto.setup

Query

まずは schema を定義します。lib/graphql_sample_web/schema.ex として以下内容を記載します。
見てなんとなく分かりますが、object :link do ... で link という object を定義、query do ...allLinks クエリを定義しています。

lib/graphql_sample_web/schema.ex
defmodule GraphqlSampleWeb.Schema do
  use Absinthe.Schema

  alias GraphqlSampleWeb.NewsResolver

  object :link do
    field :id, non_null(:id)
    field :url, non_null(:string)
    field :description, non_null(:string)
  end

  query do
    field :all_links, non_null(list_of(non_null(:link))) do
      resolve &NewsResolver.all_links/3
    end
  end
end

Absinthe が all_links を GraphQL 用に allLinks に変換してくれるようです。

GraphqlSampleWeb.NewsResolver module は別途定義が必要で、以下のように lib/graphql_sample_web/resolvers/news_resolvers.ex へ定義します。

lib/graphql_sample_web/resolvers/news_resolvers.ex
defmodule GraphqlSampleWeb.NewsResolver do
  alias GraphqlSample.News

  def all_links(_root, _args, _info) do
    links = News.list_links()
    {:ok, links}
  end
end

このレベルであれば Resolver なくてもという感じですが、複雑になってくることを考えるとこういった層を挟むことで複雑度を抑えられるのかなという感触。module 分けたり、よりテスタブルになったりね。

動作確認のための設定

GraphiQL というブラウザで動くライブラリを使って GraphQL の動作を確認します。
以下のように router.ex へ追加することで /graphiql が GraphQL 用のエンドポイントとして有効になるようです。

lib/graphql_sample_web/router.ex
  scope "/" do
    pipe_through :api

    forward "/graphiql", Absinthe.Plug.GraphiQL,
      schema: GraphqlSampleWeb.Schema,
      interface: :simple,
      context: %{pubsub: GraphqlSampleWeb.Endpoint}
  end

$ iex -S mix phx.server でアプリを立ち上げ localhost:4000/graphiql へアクセスすると、こんな画面が表示されます。

GraphiQL の画面

左側のペインに以下クエリを入力して実行すると、link table に格納されているデータが返ってきます。

{
  allLinks {
    id
    url
    description
  }
}

Mutation

次にデータ操作のための Mutation を試します。

lib/graphql_sample_web/schema.ex へ以下を追加します。
arg というのが初めて出てきていますが、これはその名の通り引数です。
これも結構見た目通りなので、Absinthe 頑張ってくれているなと思います。

lib/graphql_sample_web/schema.ex
  mutation do
    field :create_link, :link do
      arg :url, non_null(:string)
      arg :description, non_null(:string)

      resolve &NewsResolver.create_link/3
    end
  end

Resolver 側には以下を追加します。

lib/graphql_sample_web/resolvers/news_resolvers.ex
  def create_link(_root, args, _info) do
    case News.create_link(args) do
      {:ok, link} ->
        {:ok, link}
      _error ->
        {:error, "could not create link"}
    end
  end

ここまで出来たらアプリを立ち上げてクエリ同様に localhost:4000/graphiql へアクセスします。

今度は左のペインへ以下のように入力して実行します。

mutation {
  createLink(
    url: "https://github.com/ma2gedev/power_assert_ex",
    description: "Power Assert Elixir",
  ) {
    id
    url
    description
  }
}

これで link table へ追加されました。再度クエリで allLinks を叩くことで結果が増えていることが確認できます。

まとめ

REST との違いを感じることができたので、とりあえず入り口くらいには立てたかなと。
ただ client 側で必要なものだけを取るとか、N+1 を解消させる例とか試したいところが全然試せていない感じなので、GraphQL を理解するにはもう少し頑張らねば。。。

Resources

12
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ma2ge
Programmer
m3dev
インターネット、最新IT技術を活用し日本・世界の医療を改善することを目指します

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
12
Help us understand the problem. What is going on with this article?