勉強したことのメモ
GraphQL
RESTでは一つのAPIアクセスに対して一つの決まった形のデータしか取ってくることができなかったが、graphQLを使うと自分の好きなデータを好きな組み合わせで取ってくることができる。そんな便利なGraphQLを使うには、Nuxt.jsではApollo、railsでは graphql rails というライブラリ(?)を使うことになる。
GraphQLの公式ドキュメントは英語だが結構わかりやすいので根本の概念はドキュメントを読むとなんとなく掴める。
フロント側(今回はNuxt.js)
インストールは省略
nuxt.config.jsに設定を書く。
内容は叩くAPIの場所
...,
apollo: {
clientConfigs: {
httpEndpoint: `http://localhost:4000/graphql`
}
},
...
クエリ
クエリはデータくださいっていう要求のこと。
apollo/queries下に色々なクエリを書いていく
例えばapollo/queries/item.gql
# 引数の定義を書いておく
query Item($id: Int!){
# 引数を書く
item(id: $id) {
#欲しいフィールドを書いていく
id
name
price
userId
imageUrl
explanation
}
}
詳しくはドキュメント参照
ミューテーション
ミューテーションはデータを変更したり削除したりする時に使う。
apollo/mutation下にmutationファイルを書いていく。
例えば、apollo/mutation/deletelike.gql
mutation ($id: ID!){
deleteItem(input: {id: $id}){
Item {
id
}
}
}
クエリやミューテーションの使い方
例としてindex.vueで使う場合を考える。
scriptタグ内で
import (query/muationの名前) from (gqlファイル名)
例えば、
import Item from '~/apollo/querys/item.gql'
となる。
クエリで取得したデータを直接{{ item }}とかで使いたいとき
export default内で
data(){
...
},
apollo {
item: {
query: Item
}
},
...
と記述する。
そうするとtemplate内で変数itemが使えるようになる。
メソッド内で使いたいとき
deleteItemを使うときは
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が以下のように更新されたり、
...
if Rails.env.development?
mount GraphiQL::Rails::Engine, at: '/graphiql', graphql_path: '/graphql'
end
...
appディレクトリ下にgraphqlディレクトリが作成されたりする。
Types
まず、graphQLが返すデータの型を定義する必要があり、これは
app/graphql/types
下に各モデルごとにファイルを作れば良い。
例としてuserモデルのtypeファイルを以下に示す。
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を作ってその中に全部のクエリを書く。
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アクションが行われる
Rails.application.routes.draw do
...
post '/graphql', to: 'graphql#execute'
...
end
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呼び出し時のパラメータが格納されていて、指定されたクエリが呼び出されて実行される。