LoginSignup
1

More than 1 year has passed since last update.

Elixir × GraphQLシリーズ ③ ミューテーションとサブスクリプション設定の追加

Last updated at Posted at 2022-12-21

Elixir × GraphQLシリーズ

~ Abshinthe と Abshinthe crient の 連携 ~

この記事は「Elixir Advent Calendar 2022」22日目の記事です
東京にいるけどfukuokaexのYOSUKEです。

このシリーズは3部作目です。
前回までは以下

GraphQLとは

GraphQLとは、アプリケーション プログララミング インタフェース(API)の1つで、REST APIなどと違って、クエリを駆使して、1つのエンドポイントからデータを柔軟に利用したいものだけ取得する事ができる仕組みです。

詳しく知りたい方は、GraphQLの学習を参考にしてください。

今回の構成

  • よくある、GraphQLを利用した開発の構成として使われるのは、フロント側の実装を(React,VueなどのSPA)で開発し、バックエンド側をGraphQLサーバーとして開発し、1つのエンドポイントで繋いで利用する。というものだと思いますが、

  • 今回は、フロント側を LiveView を利用して、 フロントとバックを両方 Elixirで作成する方法を試していきます。

  • LiveViewを活かしたいので、クエリだけでなく、ソケットを利用したステートフルな形を準備していきます。

クエリとミューテーションとは

GraphQL の操作はクエリとミューテーションです。これらを create (作成)、read (読み取り)、update (更新)、delete (削除) (CRUD) モデルに照らして考えると、クエリは read (読み取り) に相当します。その他すべて (create、update、delete) はミューテーションによって処理されます。

クエリまでは、シリーズ①、②で実装してきましたが、ミューテーションの実装はまだでしたので、まずはミューテーションを実装していきたいと思います。

GraphQL ミューテーションの実装

スキーマにミューテーションの追加

schema.ex

defmodule OpenDataQlWeb.Schema.Schema do
  use Absinthe.Schema

# 省略 #

  mutation do
    field :create_place, :place do
      arg :lat, non_null(:float)
      arg :location, non_null(:string)
      arg :lon, non_null(:float)
      arg :name, non_null(:string)
      arg :scale, non_null(:integer)
      resolve &OpenDataQlWeb.Resolvers.Community.create_place/3
    end
  end

end

リゾルバの作成

community.ex
defmodule OpenDataQlWeb.Resolvers.Community do
  alias OpenDataQl.Community
# 省略 #
  def create_place(_, params, _) do
    case Community.create_place(params) do
      {:error, _} -> {:error, "Could not create place"}
      {:ok, _} = success -> success
    end
  end

早速試してみましょう。
Firefox のADD ON にある GraphQL Clientからミューテーションを実行してみます。

スクリーンショット 2022-12-12 12.05.51.png

今回は、変数を使わず、直接値を入力してミューテーションを実行してみました。

mutation{
  createPlace(name: "name5", lat: 123.4, lon: 234.5, location: "name", scale: 9){
    name
	lat
    lon
    location
    scale
    id
  }
}

スクリーンショット 2022-12-12 12.03.18.png

ちゃんと挿入されているか確認してみましょう。以下のクエリを実行して確認します。

{
  places{
    name
    scale
    location
    lat
    lon
    id
  }
}

以下のように先ほどmutationで挿入したデータがちゃんと取得できることが確認できました。

スクリーンショット 2022-12-12 12.09.20.png

GraphQL サブスプリクションの実装

GraphQL サブスクリプションは、サーバー内のイベントでデータをクライアントにリアルタイムでプッシュする方法になります。

クライアントは、特定のデータを要求するサブスクリプションを送信します。イベントが発生すると、そのイベントに対して実行され、結果のデータがプッシュされます。

そこで、ソケットを利用します。以下のコマンドでソケットを準びします。

ソケットの追加

$ mix phx.gen.socket User

2つファイルが生成されます。また、以下2つのファイルに関連付けを追記します。

lib/open_data_ql_web/endpoint.ex
    socket "/socket", OpenDataQlWeb.UserSocket,
      websocket: true,
      longpoll: false
assets/js/app.js
    import "./user_socket.js"
user_socket.ex
defmodule OpenDataQlWeb.UserSocket do
  use Phoenix.Socket
  use Absinthe.Phoenix.Socket, schema: OpenDataQlWeb.Schema.Schema #<- 追記

サブスクリプションの実装

Application 監視ツリーに追記

application.ex
  def start(_type, _args) do
    children = [
# 省略 #
      {Phoenix.PubSub, [name: OpenDataQl.PubSub, adapter: Phoenix.PubSub.PG2]},
      {Absinthe.Subscription, OpenDataQlWeb.Endpoint}
    ]

EndpointにAbsinthe.Phoenix.Endpointを追加

endpoint.ex
defmodule OpenDataQlWeb.Endpoint do
  use Phoenix.Endpoint, otp_app: :open_data_ql
  use Absinthe.Phoenix.Endpoint #<-追加

GraphiQL プラグを使用している場合は、 routerでsocketオプションを指定します。

router.ex
  if Mix.env() == :dev do
    forward "/graphiql", Absinthe.Plug.GraphiQL,
      schema: OpenDataQlWeb.Schema.Schema,
      interface: :simple,
      socket: OpenDataQlWeb.UserSocket
  end

これで準びは完了です。

いよいよ、サブスクリプションの中身を実装して確認していきたいのですが、長くなりそうなので、サブスクリプションの実装編はまた時間ある時に何回かに分けて続きを書こうと思います。

今年は、サクッと書くのがコンセプトなので、(大作しすぎると続かなくなるので、今年はサクッと継続を重視していこうかと)

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1