RailsでGraphQLを使う

結構使いやすくなっていたので紹介

セットアップ

# Gemfile
gem 'graphql'
rails generate graphql:install

まず導入 基本的な構成と、graphiql(GraphQLのクライアントをRailsにマウントするやつ)が入る

http://localhost:3000/graphiql

サンプルフィールドが用意されているのでクエリを叩くと、結果が得られる。 f:id:anoChick:20170521182758p:plain

こんなかんじ。

ActiveRecordとつなげる

Railsで使うからにはGraphQLのObjectとRailsのモデルを繋げなければいけません。 つなぐために

GitHub - goco-inc/graphql-activerecord

このGemを使います。

rails g model Book name:string

こんなモデルを予め作っておいてください。

# Gemfile
gem 'graphql-activerecord'
bundle install

レコード作成

まずはBookモデルに対応したBookTypeを作ります。

# app/graphql/types/book_type.rb
Types::BookType = GraphQL::ObjectType.define do
  name "Book"
  backed_by_model :books do
    attr :name
  end
end

次にBookを新たに作成するためのMutationを定義します。

# app/graphql/mutations/create_book.rb
Mutations::CreateBook = GraphQL::Relay::Mutation.define do
  name "CreateBook"

  return_field :book, Types::BookType
  input_field :name, !types.String

  mutator_definition = GraphQL::Models.define_mutator(self, Book, null_behavior: :leave_unchanged) do
    attr :name
  end
  resolve ->(obj, args, ctx) {
    { book: Book.create(name:args[:name]) }
  }
end

あとは、このMutationを

App名Schemaに認識させます。

# app/graphql/types/mutation_type.rb

Types::MutationType = GraphQL::ObjectType.define do
  name 'Mutation'
  field :CreateBook, field: Mutations::CreateBook.field
end
# app/graphql/アプリ名_schema.rb

アプリ名Schema = GraphQL::Schema.define do
  query(Types::QueryType)
  mutation(Types::MutationType) # 追加

  lazy_resolve(Promise, :sync)
  instrument(:query, GraphQL::Batch::Setup)
  instrument(:field, GraphQL::Models::Instrumentation.new)
end

これで叩ける用にはなりました。

f:id:anoChick:20170521194025p:plain 問題なければDBにレコードが作成されているはずです。

queryを使う。

先程BookTypeは作ってしまったので、QueryTypeを記述するだけです。

# app/graphql/types/query_type.rb

Types::QueryType = GraphQL::ObjectType.define do
  name "Query"
  
  field :book, Types::BookType do
    description "An example field added by the generator"
    argument :id, !types.ID
    resolve ->(obj, args, ctx) {
      Book.find(args[:id])
    }
  end
end

f:id:anoChick:20170521194524p:plain

関連レコードも引っ張ってくる

これだけだとつまらないので関連データもとってこれるようにしたいと思います。 デモ用モデルとして「登場人物」を新たに作ります。

rails g model Character name:string book:references

次に CharacterTypeを定義します。 ちなみに、

rails g graphql:object Character

で作ることも出来る。

# app/graphql/types/book_type.rb
Types::BookType = GraphQL::ObjectType.define do
  name "Book"
  backed_by_model :books do
    attr :name
    has_many_array :characters # 追加
  end
end

今日の雑記はgraphql-activerecord - あのにのに

でも書いたけど Typeの定義の仕方によっては一手間必要・

f:id:anoChick:20170521213806p:plain

できたできた。