graphql-rubyの話

# 今日話すこと

---
## ほとんど http://graphql-ruby.org/ に書いてあります。

---
# アジェンダ
- 自己紹介
- graphQL is 何？
- graphql-rubyの実装
- graphql-rubyのテスト
- graphql-rubyのn+1

---
# 自己紹介

---
# 自己紹介

- 名前：やまたつ
- 会社：giftee
- 仕事：rails書いたりfront書いたり

---
# graphQL is 何？

---
# graphQL is 何？

- RESTfulの代替
- facebook発
- url
    - http://graphql.org/
- graphql-ruby
    - http://graphql-ruby.org/
- RFC
    - [草案提出中](https://facebook.github.io/graphql/)
- QLはquery languageのこと
- SQLみたいな気分でapiを呼び出す

---
# graphQL is 何？
query 

```
{
  human(id: "1000") {
    name
    height(unit: FOOT)
  }
}
```

```json
{
  "data": {
    "human": {
      "name": "Luke Skywalker",
      "height": 5.6430448
    }
  }
}
```

---
# graphQL is 何？
mutation

```
mutation {
  addHuman(
    name: "ほげほげ"
    height: 1.8
  ) {
    human {
      name
      height
    }
  }
}
```

```json
{
  "data": {
    "human": {
      "name": "Luke Skywalker",
      "height": 5.6430448
    }
  }
}
```

---
# graphQL is 何？

||RESTful|graphQL|
|---|---|---|
|エンドポイント|いっぱい|基本１つ|
|呼び出し回数|多くなりがち|１回でいろんな情報が取れる|
|条件文|urlパラメータ|クエリで書ける|
|HTTPメソッド|Get, Post, Put, Delete|Post|

--- 
# graphql-rubyの実装

--- 
# graphql-rubyの実装
始め方

```rb:Gemfile
gem 'graphql'
```

```sh:sh
$ bundle
$ rails g graphql:install
$ bundle
```

`rails g graphql:install` すると`graphiql-rails`というgemが勝手にGemfileに書き加えられるので、もっかい`bundle`

--- 
# graphql-rubyの実装
routesが変わる

```rb:config/routes.rb
Rails.application.routes.draw do
  if Rails.env.development?
    mount GraphiQL::Rails::Engine, at: "/graphiql", graphql_path: "/graphql"
  end

  post "/graphql", to: "graphql#execute"
end
```
- エンドポイントひとつ
- graphiQLは後述

--- 
# graphql-rubyの実装
controllerが加わる

```rb:app/controllers/graphql_controller.rb
class GraphqlController < ApplicationController
  def execute
    variables = ensure_hash(params[:variables])
    query = params[:query]
    context = {
      # Query context goes here, for example:
      # current_user: current_user,
    }
    result = MyappSchema.execute(query, variables: variables, context: context)
    render json: result
  end


  private
  ...
end
```

---
# graphql-rubyの実装
`app/graphql`の下にschema定義が加わる

```rb:app/graphql/myapp_schema.rb
MyappSchema = GraphQL::Schema.define do
  query(Types::QueryType)
end
```

```rb:app/graphql/types/query_type.rb
Types::QueryType = GraphQL::ObjectType.define do
  name "Query"
  # Add root-level fields here.
  # They will be entry points for queries on your schema.

  # TODO: remove me
  field :testField, types.String do
    description "An example field added by the generator"
    resolve ->(obj, args, ctx) {
      "Hello World!"
    }
  end
end
```
- これを書いていきます

--- 

# schema定義 is 何？

---

# schema定義 is 何？
- SQLではschema(テーブル定義とか)を決めると使えるクエリがきまる
- それと同じ

---

# schema定義 is 何？
ソース見せる
https://github.com/yamatatsu/graphql-ruby-playground/

---

## schema定義読まなきゃ呼び出し方分からないとか辛い :cry:

---

## そこでGraphiQL

---
## GraphiQL is 何？
- 読み方
    - ɡrafək(ə)l
    - たぶん [グラフィクル] でいいと思う(発音記号読めない)
- スキーマ定義をもとに実装者向けのクエリの実行環境とDocとをいい感じに出してくれる

GraphiQL見せる
http://localhost:3000/graphiql

---
## GraphiQLべんり

---
# graphQL(graphql-ruby)で良かったこと
- フロントからのapi呼び出しが減る
    - api呼び出し周りのフロントのコードが減る
- mutationの表現力
    - 命名の自由度が高い
    - 引数もschemaで定義できる
        - 引数もGraphiQLでドキュメント化される
- apiのurlなんだっけ？ がなくなる
    - GraphiQLで呼び出し方見る
- 応答のjsonの形なんだっけ？ がなくなる
    - GraphiQLでjsonの形を確認する

---
# graphQL(graphql-ruby)でいやなこと
- GraphiQLがmountで動いてる
    - 再起動しないと読み込まれない(調査中)
        - 実装時はGraphiQLではなくテストに頼ろう
- `''`だと構文エラー
    - `""`で動く。わすれがち。
- クライアント側のライブラリが分厚い（のが多い）
    - RESTの代替として小さく始めたい
    - Relay, ApolloはReact世界への侵食が必要（apolloは違うかも?）
    - Lokkaを使ってる
- schemaの書き方がキモい。めんどい
    - めちゃめちゃ記述量が減る[issues](https://github.com/rmosolgo/graphql-ruby/issues/727), [PR](https://github.com/rmosolgo/graphql-ruby/pull/789)が出てる
- すぐにn+1する
    - 後述

---
# graphql-rubyのテスト

---
# graphql-rubyのテスト

[本家サイト](http://graphql-ruby.org/schema/testing.html)転用

- Don’t test the schema, test other objects instead
- Test schema elements (types, fields) in isolation
- Execute GraphQL queries and test the result

--- 
# 割愛

--- 
# graphql-rubyのn+1

---
# graphql-rubyのn+1
- スキーマごとにDBアクセスするので簡単にn+1する  
    <img width="50%" alt="ファイル名" src="https://i.gyazo.com/19abe62d87bfa5ee56d36c43a1b6c642.png">
    - デモ：https://github.com/yamatatsu/graphql-ruby-playground/tree/n1
- graphql-batchという解決策が提示されている

---
# graphql-batch is 何？

---

# graphql-batch is 何？
- https://github.com/Shopify/graphql-batch
- gemです
    - graphql-ruby用のgem
    - sql呼び出しを遅延評価するためのgem
- 公式サイトのサンプルだと belongs_to な関連でのn+1でしか使えない
    - issuesにいい感じのLoader実装が載ってる
        - https://github.com/Shopify/graphql-batch/issues/24
        - https://gist.github.com/theorygeek/a1a59a2bf9c59e4b3706ac68d12c8434
- ぼくがかんがえるさいきょうのloader
    - https://github.com/yamatatsu/graphql-ruby-playground/blob/master/app/graphql/association_loader.rb

---
# まとめ

---
# graphQLいいぞ

---
# 再掲

- 名前：やまたつ
- 会社：giftee
    - rails5.1, graphql, react, aws, docker
    - 場所：五反田駅から徒歩3分
    - フレックスタイム
    - [エンジニア募集中](https://www.wantedly.com/projects/53169)
    - お気軽に[meet up](https://giftee.connpass.com/event/59942/)にご参加下さい
        - 6/30(金)開催！
        - 6/23(金)締め切り！
        - 今回のテーマはメキシカン！！
- 仕事：rails書いたりfront書いたり

---

# ご清聴ありがとうございました :bow: