Rails:GraphQL API の構築手順

2021/02/26に公開

Rails で GraphQL API を構築する手順を整理します。

公式ドキュメント

https://graphql-ruby.org/getting_started.html

前提

こちらの手順に従い、開発環境を構築していることを前提とします。

https://zenn.dev/kei178/articles/43172ba33eece4

1. GraphQL のセットアップ

インストール

graphql をインストールします。

project-backend/Gemfile
+ gem 'graphql'

起動している backend のプロセス名を確認し、コンテナ内に入ります。

docker ps
docker exec -it project_backend_1 sh

インストールコマンドを実行します。

bundle install
bundle exec rails g graphql:install

必要なファイル群が app/graphql 下に生成されます。

2. GraphQL クエリ

リソース Post のデータを GraphQL で取得できるようにします。

型の作成

リソース Post の型を PostType で定義します。

project-backend/app/graphql/types/post_type.rb
module Types
  class PostType < Types::BaseObject
    description "A blog post"
    field :id,    ID,     null: false
    field :title, String, null: false
    field :body,  String, null: false
  end
end

クエリの作成

続いて、クエリロジックを定義します。

BaseQuery

project-backend/app/graphql/queries/base_query.rb
module Queries
  class BaseQuery < GraphQL::Schema::Resolver; end
end
  • クエリ関連のファイルは app/graphql/queries にまとめます。

PostsQuery

Post の一覧を取得。

project-backend/app/graphql/queries/posts_query.rb
module Queries
  class PostsQuery < Queries::BaseQuery
    type [Types::PostType], null: false

    def resolve
      Post.limit(50)
    end
  end
end

PostQuery

ID指定で該当する Post を1件取得。

project-backend/app/graphql/queries/post_query.rb
module Queries
  class PostQuery < Queries::BaseQuery
    type Types::PostType, null: false
    argument :id, ID, required: true

    def resolve(id:)
      Post.find(id)
    end
  end
end

定義したクエリを QueryType に記載し、ルートクエリとして取得できるようにします。

project-backend/app/graphql/types/query_type.rb
module Types
  class QueryType < Types::BaseObject
    # Add `node(id: ID!) and `nodes(ids: [ID!]!)`
    include GraphQL::Types::Relay::HasNodeField
    include GraphQL::Types::Relay::HasNodesField

    # Add root-level fields here.
    # They will be entry points for queries on your schema.
    field :posts, resolver: Queries::PostsQuery
    field :post,  resolver: Queries::PostQuery
  end
end

GraphiQL で動作確認

テストツール「GraphiQL」で動作確認してみます。

field :posts

GraphiQL で posts を取得

field :post

GraphiQL で post(id:) を取得

問題なく動いています。

3. GraphQL ミューテーション

リソース Post のデータを GraphQL で更新できるようにします。

ミューテーションの作成

PostInputType

更新処理に必要なインプットデータの型を定義します。

project-backend/app/graphql/types/input/post_input_type.rb
module Types
  module Input
    class PostInputType < GraphQL::Schema::InputObject
      argument :id,    Int,    required: true
      argument :title, String, required: false
      argument :body,  String, required: false
    end
  end
end
  • インプットデータの型は app/graphql/types/input にまとめます。

UpdatePost

該当する Post を更新する処理を定義します。

project-backend/app/graphql/mutations/update_post.rb
module Mutations
  class UpdatePost < Mutations::BaseMutation
    argument :params, Types::Input::PostInputType, required: true

    def resolve(params:)
      post_params = params.to_h
      post = Post.find(post_params.delete(:id))
      post.update!(post_params.compact)
      post
    end
  end
end
  • ミューテーションは app/graphql/mutations にまとめます。

MutationType

定義した更新処理を MutationType に記載します。

project-backend/app/graphql/types/mutation_type.rb
module Types
  class MutationType < Types::BaseObject
    field :update_post, Types::PostType, mutation: Mutations::UpdatePost
  end
end

GraphiQL で動作確認

テストツール「GraphiQL」で動作確認してみます。

変数

{
  "params": {
    "id": 1,
    "title": "Title updated from GraphQL"
  }
}

クエリ

mutation($params: PostInputType!) {
  updatePost(input: { params: $params }) {
    id
    title
  }
}
  • キー input にオブジェクトを持たせないとエラーが出ます。

実行結果

mutation updatePost の動作確認

問題なく更新されています。

次のステップ

フロントエンド Apollo Client の構築手順をまとめています。

https://zenn.dev/kei178/articles/8c6ad6fd91c9de

Discussion