5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

知識0のバカでも分かったgraphQL (Apollo, graphql-rails)

Last updated at Posted at 2019-12-29

勉強したことのメモ

GraphQL
RESTでは一つのAPIアクセスに対して一つの決まった形のデータしか取ってくることができなかったが、graphQLを使うと自分の好きなデータを好きな組み合わせで取ってくることができる。そんな便利なGraphQLを使うには、Nuxt.jsではApollo、railsでは graphql rails というライブラリ(?)を使うことになる。

GraphQLの公式ドキュメントは英語だが結構わかりやすいので根本の概念はドキュメントを読むとなんとなく掴める。

フロント側(今回はNuxt.js)

インストールは省略
nuxt.config.jsに設定を書く。
内容は叩くAPIの場所

nuxt.config.js
...,
apollo: {
    clientConfigs: {
      httpEndpoint: `http://localhost:4000/graphql`
    }
  },
...

クエリ

クエリはデータくださいっていう要求のこと。
apollo/queries下に色々なクエリを書いていく
例えばapollo/queries/item.gql

item.gql
# 引数の定義を書いておく
query Item($id: Int!){
  # 引数を書く
  item(id: $id) {
    #欲しいフィールドを書いていく
    id
    name
    price
    userId
    imageUrl
    explanation
  }
}

詳しくはドキュメント参照

ミューテーション

ミューテーションはデータを変更したり削除したりする時に使う。
apollo/mutation下にmutationファイルを書いていく。
例えば、apollo/mutation/deletelike.gql

deleteItem.gql
mutation ($id: ID!){
  deleteItem(input: {id: $id}){
    Item {
      id
    }
  }
}

クエリやミューテーションの使い方

例としてindex.vueで使う場合を考える。

scriptタグ内で
import (query/muationの名前) from (gqlファイル名)

例えば、

index.vue
import Item from '~/apollo/querys/item.gql'

となる。

クエリで取得したデータを直接{{ item }}とかで使いたいとき

export default内で

index.vue
data(){
  ...
},
apollo {
  item: {
    query: Item
  }
},
...

と記述する。
そうするとtemplate内で変数itemが使えるようになる。

メソッド内で使いたいとき

deleteItemを使うときは

index.vue
method(){
  ...,
  hoge(){
    this.$apollo.mutate({
      mutation: deleteItem,
      #以下で定義する変数はmutationファイル内で定義した変数たち
      variables: {
        id: id
      }
    })
  }
  ...
}

こんな感じ。queryを使いたいときは$apollo.queryにしてquery: Itemにすれば良い。

おまけ

mutateした後は更新しないと見た目には反映されないので、

refetchQueries: [{
          query: getUsersGql
        }]

などを実行するとよい。

サーバー側(今回はrails)

Gemfile

gem 'graphiql-rails'
gem 'graphql'

と書いてbundle install した後に
rails g graphql:installすると、railsが自動で色々と設定してくれる。
routes.rbが以下のように更新されたり、

routes.rb
...
if Rails.env.development?
  mount GraphiQL::Rails::Engine, at: '/graphiql', graphql_path: '/graphql'
end
...

appディレクトリ下にgraphqlディレクトリが作成されたりする。

Types

まず、graphQLが返すデータの型を定義する必要があり、これは
app/graphql/types
下に各モデルごとにファイルを作れば良い。
例としてuserモデルのtypeファイルを以下に示す。

app/graphql/types/user_type.rb
Types::UserType = GraphQL::ObjectType.define do
  # 型名
  name 'User'
  # field :(要素名), (要素のタイプ(int, string, etc))
  field :name, !types.String
  field :email, !types.String
end

クエリ

Typesファイルに定義された型を返すように要求するクエリを書いていく。

app/graphql/types/query_type.rbを作ってその中に全部のクエリを書く。

app/graphql/types/query_type.rb
module Types
  class QueryType < Types::BaseObject
    # まずはクエリの大枠だけ書く
    # field :(クエリ名), Types::(定義した型名), null: (true/false) do
    field :user, Types::UserType, null: false do
      description 'ユーザ情報を1件取得する'  # クエリの説明
      argument :id, Int, required: true, description: 'ユーザID'  # クエリに回す引数
    end
    
    # 上のクエリの詳細の動きをクエリ名と同じ関数名で書く
    def user(id:)
      User.find(id)
    end
  end
end

実行される流れ

/graphqlにアクセスするとgraphController内のexecuteアクションが行われる

routes.rb
Rails.application.routes.draw do
  ...
  post '/graphql', to: 'graphql#execute'
  ...
end
graphqlController.rb
class GraphqlController < ApplicationController
  ...
  def execute
    variables = ensure_hash(params[:variables])
    query = params[:query]
    operation_name = params[:operationName]
    context = {}
    result = ApiSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
    render json: result
  end
  ...

paramsにはquery呼び出し時のパラメータが格納されていて、指定されたクエリが呼び出されて実行される。

5
6
0

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
5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?