GraphQLの導入経緯
当初は導入するつもりはなかったのですが、新しくジョインするところがRails&GraphQLでバックエンドを実装しているらしいので練習がてら急遽導入することに決めました。
これまではshopifyのカートシステムのgraphQLAPIを使ってフロントを実装する、ということはやっていたので呼び出し側ではgraphQL使ったことがありますが、APIを作成したことはなかったので慣れておかないと…
GraphQLがどんなものかとか、REST APIとどう違うかなどは他に良い記事がいくつもあるので省略。
GraphQLのインストール
GraphQL公式のRails用チュートリアルをみながら進めていきます。
まずはgemをダウンロード
Gemfileに追加して、
gem "graphql"
コマンド実行
$ docker-compose run --rm web bundle install
$ docker-compose run --rm rails g graphql:install
もう一度bundle install
が必要な場合があるそうです。
$ docker-compose run --rm web bundle install
これでインストールが完了。
実装
今回はコード譜をScore
というオブジェクトで表現したいと考えているので、そのテーブルを最初に作成します。
まずはテーブル作成。
持たせる属性はとりあえずtitleだけ
$ docker-compose run --rm web bundle exec rails g model Score title:string
$ docker-compose run --rm web bundle exec rails db:migrate
そしてGraphQLオブジェクトを以下のコマンドで作成。
最後に指定しているScore
と同名のテーブル(↑でつくったやつ)から型定義ファイルを作成してくれます。
$ docker-compose run --rm web rails g graphql:object Score
/app/graphql/types/score_type.rb
が作成されます。
# frozen_string_literal: true
module Types
class ScoreType < Types::BaseObject
field :id, ID, null: false
field :title, String
field :created_at, GraphQL::Types::ISO8601DateTime, null: false
field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
end
end
特に指定していないのにちゃんとtitle
も反映されていますね
/app/graphql/types/query_type.rb
を編集。
schemaを定義します。いったんqueryだけ
module Types
class QueryType < Types::BaseObject
# Add `node(id: ID!) and `nodes(ids: [ID!]!)`
include GraphQL::Types::Relay::HasNodeField
include GraphQL::Types::Relay::HasNodesField
field :scores, [Types::ScoreType], null: false
def scores
Score.all
end
field :score, Types::ScoreType, null: false do
argument :id, Int, required: false
end
def score(id:)
Score.find(id)
end
end
end
これでGraphQL使えるようになったと思うので、コンソールで動き確かめてみます。
$ docker-compose rum --rm web bundle exec rails c
でコンソール起動
> Score.create(title: "title")
でデータ作成。
公式ではGraphQL::Schema
を継承したクラスを作成していますが、AppSchemaでも動作確認できました。
> AppSchema.execute("{scores{id title}}").to_hash
Score Load (17.1ms) SELECT `scores`.* FROM `scores`
=> {"data"=>{"scores"=>[{"id"=>"1", "title"=>"title"}]}}
ちゃんと取得できてそうです!
uuidにしたいけどmysqlじゃ難しいっぽいな…
とりあえずここまで。次回はフロントで表示するところまでやろうかと思います!
補足
graphqlの動作をローカルのサーバー上で確認できるgraphiql
というgemがあるらしいのですが、ActionDispatch::Request::Session::DisabledSessionError
とエラーが出て表示できず。
Rails7系からAPIモードにするとセッション無効になるとかで、良い解決方法は無さそうだったので今回はこのgemの使用は見送りました。コンソールでも確認できたし別にいいかな。apollo使えればそれで同じこともできるはずなので。