RailsでGraphQLを使う

August 18, 2022

確認環境

$ bundle exec ruby --version
ruby 2.7.5p203 (2021-11-24 revision f69aeb8314) [x86_64-darwin19]
$ bundle exec rails --version
Rails 6.0.4.6

Graphql インストール

Gemfile

gem 'graphql'
$ bundle install
$ rails generate graphql:install

これでリクエストの送信が確認できるようになりました。

http://localhost:3000/graphiql

Query の確認

$ rails g model Post title:string description:text
$ rake db:migrate

type を定義する

$ rails g graphql:object Post

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.
    #
    # First describe the field signature:
    field :post, PostType, "Find a post by ID" do
      argument :id, ID
    end

    # Then provide an implementation:
    def post(id:)
      Post.find_by(id: id)
    end

    field :posts, [Types::PostType], null: false
    def posts
      Post.all
    end

    # TODO: remove me
    field :test_field, String, null: false,
      description: "An example field added by the generator"
    def test_field
      "Hello World!"
    end
  end
end

※ Query で確認する前にデータ登録しておいてください。

先に Mutation を作っておいた方が便利かもしれません。

graphiql にて

特定のIDのPostを取得するQuery

{
 post(id:1) {
   id
   title
   description
 }
}

// 結果
{
  "data": {
    "post": {
      "id": "1",
      "title": "hoge1",
      "description": "fuga1"
    }
  }
}

全件取得するQuery

{
 posts {
   id
   title
   description
 }
}

// 結果
{
  "data": {
    "posts": [
      {
        "id": "1",
        "title": "hoge1",
        "description": "fuga1"
      },
      {
        "id": "2",
        "title": "hoge2",
        "description": "fuga2"
      }
    ]
  }
}

Mutation (新規作成) の確認

$ rails g graphql:mutation CreatePost

app/graphql/mutations/create_post.rb

module Mutations
  class CreatePost < BaseMutation
    # define return fields
    field :post, Types::PostType, null: false
    field :result, Boolean, null: false

    # define arguments
    argument :title, String, required: true
    argument :description, String, required: false

    # define resolve method
    def resolve(**args)
      post = Post.create(title: args[:title], description: args[:description])

      {
        post: post,
        # createの結果を返す
        result: post.errors.blank?
      }
    end
  end
end

Post を作成する

mutation {
  createPost(
    input:{
      title: "title1"
      description: "description1"
    }
  ) {
    post {
      id
      title
      description
    }
    result
  }
}

## 結果
{
  "data": {
    "createPost": {
      "post": {
        "id": "11",
        "title": "title1",
        "description": "description1"
      },
      "result": true
    }
  }
}

Mutation (更新) の確認

$ rails g graphql:mutation UpdatePost

app/graphql/mutations/update_post.rb

module Mutations
  class UpdatePost < BaseMutation
    # define return fields
    # field :post, Types::PostType, null: false
    field :post, Types::PostType, null: false
    field :result, Boolean, null: false

    # define arguments
    argument :id, ID, required: true
    argument :title, String, required: false
    argument :description, String, required: false

    # define resolve method
    def resolve(**args)
      post = Post.find(args[:id])
      post.update(title: args[:title], description: args[:description])

      {
        post: post,
        # updateの結果を返す
        result: post.errors.blank?
      }
    end
  end
end

Post を更新する

mutation {
  updatePost(
    input:{
      id: 1
      title: "Updated"
      description: "UPdated"
    }
  ){
    post {
      id
      title
      description
    }
    result
  }
}

## 結果
{
  "data": {
    "updatePost": {
      "post": {
        "id": "1",
        "title": "Updated",
        "description": "UPdated"
      },
      "result": true
    }
  }
}

Mutation (削除) の確認

$ rails g graphql:mutation DeletePost

graphql/mutations/delete_post.rb

module Mutations
  class DeletePost < BaseMutation
    # define return fields
    field :post, Types::PostType, null: false
    field :result, Boolean, null: false

    # define arguments
    argument :id, ID, required: true

    # define resolve method
    def resolve(**args)
      post = Post.find(args[:id])
      post.destroy

      {
        post: post,
        # deleteの結果を返す
        result: post.errors.blank?
      }
    end
  end
end

Post を削除する

mutation {
  deletePost(
    input:{
      id: 1
    }
  ) {
    post {
      id
      title
      description
    }
    result
  }
}

## 結果
{
  "data": {
    "deletePost": {
      "post": {
        "id": "1",
        "title": "Updated",
        "description": "UPdated"
      },
      "result": true
    }
  }
}

参考


SHARE

Profile picture

Written by tamesuu