【3分入門】コピペで導入！ railsでgraphql

【3分入門】コピペで導入 ooo シリーズ第一弾です。

rails に graphqlを導入していきます。

https://github.com/nishisuke/graphql-rails-minimum-sample

graphql とは？
https://graphql.org/learn/

## install
```
# Gemfile

gem 'graphql'
```

```
$ bundle
```

## models
|users|type|
|:--|:--:|
|name|String|
|age|Integer|

```app/models/user.rb
class User < ApplicationRecord
  def friends
    %i[user mate_user].inject(Friend.none) do |friends_query, column_name|
      friends_query.or(Friend.where(column_name => self))
    end
  end
end
```

|friends|type|
|:--|:--:|
|user_id|Integer|
|mate_user_id|Integer|

```app/models/friend.rb
class Friend < ApplicationRecord
  belongs_to :user
  belongs_to :mate_user, class_name: :User

  def pairs
    [user, mate_user]
  end
end
```
friend model has two users.

## setup
```app/graphql/graphql_rails_minimum_sample_schema.rb
class GraphqlRailsMinimumSampleSchema < GraphQL::Schema
  query(GqlTypes::Query)
end
```

```app/graphql/gql_types.rb
module GqlTypes
  class Query < GraphQL::Schema::Object
    field :users,   [UserType],   null: false
    field :friends, [FriendType], null: false do
      argument :user_id, Int, required: true, camelize: false
    end

    def users
      User.all
    end

    def friends(user_id:)
      User.find(user_id).friends
    end
  end
end
```

```app/graphql/gql_types/base_object.rb
module GqlTypes
  class BaseObject < GraphQL::Schema::Object
  end
end
```

```app/graphql/gql_types/friend_type.rb
module GqlTypes
  class FriendType < BaseObject
    field :pairs, [UserType], null: false
  end
end
```

```app/graphql/gql_types/user_type.rb
module GqlTypes
  class UserType < BaseObject
    field :name,       String,       null: false
    field :age,        String,       null: true
    field :created_at, String,       null: false
    field :friends,    [FriendType], null: false
  end
end
```

## execute query!!
### 注意点
1. created_atなどsnake caseのデータ名はデフォルトでcamel caseで指定する
2. camelize false を指定すればsnake caseで指定できる
3. argumentはvariablesに渡す
4. トップレベルの{}に注意(以下)

```
# queryには{}をつけない
query get_friends($user_id: Int!) {
  # camelize falseなためuserIdではない(:point_up_2: :point_down: )
  friends(user_id: $user_id) {}
}
```
```
{
  users {}
}
```

### try

```
rails c
```

```
> GraphqlRailsMinimumSampleSchema.execute('{ users { name createdAt age friends { pairs { name } } } }').to_h
=> {"data"=>{
  "users"=>[{
    "name"=>"nishi",
    "createdAt"=>"2019-04-14 04:01:37 UTC",
    "age"=>"9",
    "friends"=>[{
      "pairs"=>[{"name"=>"nishi"}, {"name"=>"tarou"}]
    }]
  }, {
    "name"=>"suke",
    "createdAt"=>"2019-04-14 04:01:37 UTC",
    "age"=>"19",
    "friends"=>[{
      "pairs"=>[{"name"=>"suke"}, {"name"=>"tarou"}]
    }]
  }, {
    "name"=>"tarou",
    "createdAt"=>"2019-04-14 04:01:37 UTC",
    "age"=>"20",
    "friends"=>[
      {"pairs"=>[{"name"=>"nishi"}, {"name"=>"tarou"}]},
      {"pairs"=>[{"name"=>"suke"},  {"name"=>"tarou"}]}
    ]
  }]
}}
```

```
> GraphqlRailsMinimumSampleSchema.execute('query get_friends($user_id: Int!) { friends(user_id: $user_id) { pairs { name } } }', variables: { user_id: User.last.id } ).to_json
=> {"data"=>{"friends"=>[
  {"pairs"=>[{"name"=>"nishi"}, {"name"=>"tarou"}]},
  {"pairs"=>[{"name"=>"suke"}, {"name"=>"tarou"}]}
]}}
```