Rails+React構成にGraphQLをインストールする
データの準備
まずは、GraphQL で叩くためのデータが必要です。
データはデータベースなどから取得するため、まずはデータベースにテーブルを作っていきましょう。
下記コマンドでモデルを作成します。
Rails では、モデルを作成することで、同時にテーブルを作成・編集するためのマイグレーションファイルが生成します。
ここではまず、User モデルを作ることとします。
User モデルには、名前・年齢・メモの情報を持ったモデルとします。
コマンドの引数でカラム名:型
を入れるとそれに合わせたマイグレーションファイルが生成できます。
$ docker-compose run --rm web rails g model User name:string age:integer memo:string
[+] Running 1/0
⠿ Container react_app-mysql-1 Running
invoke active_record
create db/migrate/20221219125045_create_users.rb
create app/models/user.rb
invoke test_unit
create test/models/user_test.rb
create test/fixtures/users.yml
上記の通り、モデルファイルとマイグレーションファイルが生成しました。
マイグレーションファイルは下記です。
class CreateUsers < ActiveRecord::Migration[7.0]
def change
create_table :users do |t|
t.string :name
t.integer :age
t.string :memo
t.timestamps
end
end
end
マイグレーションファイルが生成しているのでマイグレーションを実行しましょう。
$ docker-compose run --rm web rails db:migrate
[+] Running 1/0
⠿ Container react_app-mysql-1 Running
== 20221219125045 CreateUsers: migrating ======================================
-- create_table(:users)
-> 0.0440s
== 20221219125045 CreateUsers: migrated (0.0451s) =============================
生成完了しました。
一応、データベースコンテナ入ってテーブルできているか確認します。
$ docker-compose exec mysql bash
bash-4.4# mysql -u root -p myapp_development
Enter password:
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 15
Server version: 8.0.31 MySQL Community Server - GPL
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> desc users;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | bigint | NO | PRI | NULL | auto_increment |
| name | varchar(255) | YES | | NULL | |
| age | int | YES | | NULL | |
| memo | varchar(255) | YES | | NULL | |
| created_at | datetime(6) | NO | | NULL | |
| updated_at | datetime(6) | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
6 rows in set (0.03 sec)
mysql>
これで GraphQL を扱うためのデータ箱は準備できました。
一応、データを仮で作っておきましょう。
rails のコンソール画面から直接データを入れましょう。
$ docker-compose exec web bash
root@198460a29b69:/myapp# rails c
Loading development environment (Rails 7.0.4)
irb(main):001:0> User.create
TRANSACTION (1.0ms) BEGIN
User Create (12.9ms) INSERT INTO `users` (`name`, `age`, `memo`, `created_at`, `updated_at`) VALUES (NULL, NULL, NULL, '2022-12-24 08:29:25.928998', '2022-12-24 08:29:25.928998')
TRANSACTION (6.1ms) COMMIT
=>
#<User:0x000000401ad6d760
id: 1,
name: nil,
age: nil,
memo: nil,
created_at: Sat, 24 Dec 2022 08:29:25.928998000 UTC +00:00,
updated_at: Sat, 24 Dec 2022 08:29:25.928998000 UTC +00:00>
irb(main):002:0> User.all
User Load (3.0ms) SELECT `users`.* FROM `users`
=>
[#<User:0x000000401aba4b18
id: 1,
name: nil,
age: nil,
memo: nil,
created_at: Sat, 24 Dec 2022 08:29:25.928998000 UTC +00:00,
updated_at: Sat, 24 Dec 2022 08:29:25.928998000 UTC +00:00>]
irb(main):003:0>
とりあえずは仮データなので、基本 Null 許容としていたので create で作成可能です。
GraphQL 導入
Rails で GraphQL を扱うためには、ライブラリをインストールしましょう。
gem ファイルに下記を追加します。
gem "graphql"
その後、Gemfile が更新されたのでインストールしましょう。
$ docker-compose run --rm web bundle install
Installing sprockets 4.1.1
Installing graphql 2.0.15
Fetching sprockets-rails 3.4.2
Installing sprockets-rails 3.4.2
Fetching graphiql-rails 1.8.0
Installing graphiql-rails 1.8.0
Bundle complete! 15 Gemfile dependencies, 73 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
gem でインストールできたら、下記コマンドを実行し、環境準備します。
こちらについては、公式にも記載されている通りに進めて行きます。
$ docker-compose run --rm web rails g graphql:install
[+] Running 1/0
⠿ Container react_app-mysql-1 Running
create app/graphql/types
create app/graphql/types/.keep
create app/graphql/myapp_schema.rb
create app/graphql/types/base_object.rb
create app/graphql/types/base_argument.rb
create app/graphql/types/base_field.rb
create app/graphql/types/base_enum.rb
create app/graphql/types/base_input_object.rb
create app/graphql/types/base_interface.rb
create app/graphql/types/base_scalar.rb
create app/graphql/types/base_union.rb
create app/graphql/types/query_type.rb
add_root_type query
create app/graphql/mutations
create app/graphql/mutations/.keep
create app/graphql/mutations/base_mutation.rb
create app/graphql/types/mutation_type.rb
add_root_type mutation
create app/controllers/graphql_controller.rb
route post "/graphql", to: "graphql#execute"
route graphiql-rails
create app/graphql/types/node_type.rb
insert app/graphql/types/query_type.rb
create app/graphql/types/base_connection.rb
create app/graphql/types/base_edge.rb
insert app/graphql/types/base_object.rb
insert app/graphql/types/base_object.rb
insert app/graphql/types/base_union.rb
insert app/graphql/types/base_union.rb
insert app/graphql/types/base_interface.rb
insert app/graphql/types/base_interface.rb
insert app/graphql/myapp_schema.rb
結構なファイルが生成しました。
実装方法
GraphQL はスキーマをベースにして実装されていきます。
まずは先ほど作成した User 関係のスキーマを作って行きましょう。
下記コマンドでスキーマを生成します。
$ docker-compose run --rm web rails g graphql:object User
[+] Running 1/0
⠿ Container react_app-mysql-1
create app/graphql/types/user_type.rb
スキーマの型については、下記の種類を用意しているようです。
app/graphql/types/
ディレクトリの中に type.rb として User のスキーマが作成されました。
# frozen_string_literal: true
module Types
class UserType < Types::BaseObject
field :id, ID, null: false
field :name, String
field :age, Integer
field :memo, String
field :created_at, GraphQL::Types::ISO8601DateTime, null: false
field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
end
end
ここからスキーマを細かく定義していきます。
# frozen_string_literal: true
module Types
class UserType < Types::BaseObject
field :id, ID, null: false
field :name, String, null: false, description: "名前"
field :age, Integer, null: false, description: "年齢"
field :memo, String, null: true, description: "コメント"
field :created_at, GraphQL::Types::ISO8601DateTime, null: false
field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
end
end
user のスキーマを修正しました。
そして Rails では、web/app/graphql/types/query_type.rb
がルートスキーマの位置付けになるため、ここに先ほど作成したスキーマを定義します。
module Types
class QueryType < Types::BaseObject
# Add `node(id: ID!) and `nodes(ids: [ID!]!)`
include GraphQL::Types::Relay::HasNodeField
include GraphQL::Types::Relay::HasNodesField
# Add root-level fields here.
# They will be entry points for queries on your schema.
# TODO: remove me
field :test_field, String, null: false,
description: "An example field added by the generator"
# ユーザー情報取得
field :user, UserType, "Find a user by ID" do
argument :id, ID
end
def test_field
"Hello World!"
end
# Then provide an implementation:
def user(id:)
User.find(id)
end
end
end
Graphiql のインストール
実際の GraphQL のクエリを確認するための Playground 環境を準備します。
下記のような画面で実際に作成したクエリを確認することが可能となります。
Graphiql に関しては、Rails 側で表示するのではなく、React で表示したいので React でインストールします。
React でのインストールについては、下記 Readme に記載している通りに実行していきます。
まずは、React 側で Graphql と Graphiql を触るので、下記コマンドでインストールします。
$ docker-compose run --rm web yarn add graphiql graphql @graphiql/toolkit
インストール後は、Graphiql を実行するための、コンポーネントを用意します。
import { createGraphiQLFetcher } from "@graphiql/toolkit";
import { GraphiQL } from "graphiql";
import "graphiql/graphiql.css";
import React from "react";
export default function Graphiql() {
const fetcher = createGraphiQLFetcher({
url: "http://localhost:3000/graphql",
});
return (
<div style={{ height: "100vh" }}>
<GraphiQL fetcher={fetcher} />
</div>
);
}
Graphql のエンドポイントは、Rails の routes.rb に記載した通り、 POST メソッドの/graphql
です。
ですので、createGraphiQLFetcher
の URL にはそのエンドポイントを渡します。
React では、react-router
などを使って、http://localhost:3000/graphiql
でアクセスできるようにしておきましょう。
そうすることで、Playground が利用できるようになります。
念の為、rails 側の 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"
root 'home#index'
get '*path', to: 'home#index'
end
ちなみに下記はコメントアウトしています。
if Rails.env.development?
mount GraphiQL::Rails::Engine, at: "/graphiql", graphql_path: "/graphql"
end
が記載されていると、Rails 側の URL で、http://localhost:3000/graphiql
を表示してしまうので、コメントアウトなりで削除しましょう。
実際に Call してみる
実際に Call してみました。
このようにして実際に User 情報が取得できるようになりました。
複雑なQueryの実装について実装について
まとめ
graphql は REST と比べると柔軟な開発が可能ですので、よかったら触ってみてください。
Discussion