• トップ
  • ブログ一覧
  • Ruby on Rails & GraphQLの環境構築と実装
  • Ruby on Rails & GraphQLの環境構築と実装

    りゅうちゃん(エンジニア)りゅうちゃん(エンジニア)
    2022.07.13

    IT技術

    はじめに

    RailsとGraphQLで開発しているプロジェクトに参画したのですが、

    環境構築を1からしたことがなかったので、やり方をまとめていきたいと思います!

    GraphQLとは?

    GraphQLを導入することで、1つのエンドポイントで色々なレスポンスを返すことができます。

    どういうレスポンスが必要なのかをクライアント側で指定することができ、その指定された値だけを返す処理はGraphQLが行ってくれるので、このページではこの値は不要だとか、そういった面倒なことをバックエンド側で考える必要がなくなります。

    Rails環境の構築

    まずはGraphQL導入の前に、Rails環境構築をしていきましょう。

    Controllerを使って、DBの値を返すようなAPIを作ります。

    バージョン情報

    1$ rails -v
    2    Rails 7.0.3
    3$ ruby -v
    4    ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-darwin20]

    Hello Worldまで

    以下コマンドを入力し、Ruby on Railsのプロジェクトを作成しましょう。

    1$ rails new test_graphql_api

    そうしたら、HelloWorldを返却する用のControllerを実装します。

    app/controllers下に以下ファイルを追加しましょう。

    1class HelloController < ApplicationController
    2  def hello
    3    render json: { message: "Hello World!" }
    4  end
    5end

    あとはconfig/routes.rbにhelloの情報を追加し、

    1Rails.application.routes.draw do
    2  root "hello#hello"
    3end

    rails s コマンドを実行して、起動したサーバーにアクセスすると、HelloControllerで実装したJsonが返ってくるようになりました!

    DBを扱ったAPIを作成する

    デフォルトのrailsアプリではsqlite3が入っているので、これを使っていきます。

    以下のコマンドでUserモデルファイルを作成し、DBに反映させましょう。

    1$ rails g model User name:string age:integer
    2$ rails db:migrate

    もしモデルとテーブルを作成し直したい場合は以下コマンドでいけます。

    1$ rails d model User
    2$ rails g model User ...
    3$ rails db:migrate:reset

    これでUsersテーブルができたので、Usersテーブルを使った以下のAPIを実装します。

    • Userの追加
    • Userの一覧取得
    • 特定Userの取得

    まずはUser関連を扱うControllerクラスを作成しましょう!

    1class UsersController < ApplicationController
    2  skip_before_action :verify_authenticity_token
    3
    4  # Userの一覧取得
    5  def index
    6    users = User.all
    7    render json: users
    8  end
    9
    10  # Userの追加
    11  def add
    12    user = User.create(name: params["name"], age: params["age"])
    13    render json: user
    14  end
    15
    16  # 特定Userの取得
    17  def user
    18    user = User.find(params[:id])
    19    render json: user
    20  end
    21end

    User用のルーティングも設定します。

    1Rails.application.routes.draw do
    2  root "hello#hello"
    3
    4  get 'users', to: 'users#index'
    5  get 'users/:id', to: 'users#user'
    6  post 'users', to: 'users#add'
    7end

    これで一通りの実装が完了しました!

    動作確認

    Usersテーブルに何も入ってない状態になっているので、まずはUserデータを追加するAPIを叩きましょう。

    適当なUserをいくつか追加しておきます。

    これでUserテーブルにデータが追加されたので、他のAPIも叩いてみましょう。

    無事取得できましたね!

    GraphQLに置き換える

    ここからが本題です。

    さきほどのUsersControllerをGraphlQL化していきましょう!

    まずはGraphQLのインストールからです。

    1gem 'graphql'
    2gem 'graphiql-rails' # ブラウザ上でGraphQLを確認できるようにするやつ

    Gemfileに上記を入れて、bundle install しましょう。

    その後以下コマンドを叩くと、GraphQL用のController作成やroutes.rbの設定など自動で行ってくれます。

    1$ rails g graphql:install

    あとは上記コマンドによって作成されたapp/graphql下で、GraphQLのAPIを作成していきましょう。

    GraphQL用のUserモデルの作成

    まずはGraphQL用のUserモデルを作成します。

    以下コマンドによって、DBのテーブルを参照してapp/graphql/types下に作成されます。

    1$ rails g graphql:object User
    1# frozen_string_literal: true
    2
    3module Types
    4  class UserType < Types::BaseObject
    5    field :id, ID, null: false
    6    field :name, String
    7    field :age, Integer
    8    field :created_at, GraphQL::Types::ISO8601DateTime, null: false
    9    field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
    10  end
    11end

    まずは実装が単純な「Userの一覧取得」から実装していきましょう。

    Userの一覧取得の実装

    app/graphql下にqueries/resolversフォルダを作成し、以下のファイルを追加します。

    1module Queries
    2  module Resolvers
    3    class Users < GraphQL::Schema::Resolver
    4      type [Types::UserType], null: false
    5      description "Userの一覧取得"
    6
    7      def resolve
    8        ::User.all
    9      end
    10    end
    11  end
    12end

    そうしたら以下のコードをquery_type.rbに書き足すだけです。

    1field :users, resolver: Queries::Resolvers::Users

    Resolverを使わなくてもquery_type.rbに直接書き足していくだけでもいいのですが、実装するAPIが多くなると肥大化してしまうため、分離しています。

    これでUserの一覧取得は実装できましたので、graphiqlで確認してみましょう!

    左側がリクエストで、右側でレスポンスになります。

    さきほどのHTTPリクエストと同じようなデータが取得できていますね!

    GraphQLでは、リクエスト中のnameやageを削除することで、レスポンスを操作することが可能です。

    次にリクエスト時にidが必要な「特定Userの取得」を実装してみましょう。

    特定Userの取得の実装

    ほとんどUserの一覧取得と同じ感じで実装できます。

    まずはResolverを追加しましょう。

    1module Queries
    2  module Resolvers
    3    class User < GraphQL::Schema::Resolver
    4      type Types::UserType, null: false
    5      description "特定Userの取得"
    6
    7      argument :id, String, required: true, description: "Userのid"
    8
    9      def resolve(params)
    10        # ::Userとしているのは、Queries::Resolvers::Userとして呼ばれるのを防ぐ為
    11        ::User.find(params[:id])
    12      end
    13    end
    14  end
    15end

    最後にquery_type.rbにUserの定義を追加します。

    1field :user, resolver: Queries::Resolvers::User

    これで実装できましたので、graphiqlで確認してみましょう!

    HTTPリクエストと同じく、id:1の指定でhoge美のデータが取得できましたね!

    最後にUserの追加を実装していきましょう。

    Userの追加

    データの追加にはMutationが利用できます。

    以下コマンドを実行して、ファイルを作成しましょう。

    1$ rails g graphql:mutation AddUser

    これによってapp/graphql/mutations/add_user.rbが作成されたので、ここを編集していきます。

    1module Mutations
    2  class AddUser < BaseMutation
    3    field :user, Types::UserType, null: false
    4
    5    argument :name, String, required: true
    6    argument :age, Integer, required: true
    7
    8    def resolve(params)
    9      user = User.create(name: params[:name], age: params[:age])
    10      {
    11        "user": user
    12      }
    13    end
    14  end
    15end

    ほとんどResolverで書いたやつと同じですね。

    注意点としては、レスポンスにフィールド名を指定する必要があるため、Userモデルそのままで返すとエラーになっちゃう点です。

    query_type.rbと同じくmutation_type.rbも存在しますが、ここへの記述はさきほどのコマンド実行によって完了しています。

    1field :add_user, mutation: Mutations::AddUser

    これで実装は完了したので、graphiqlで確認していきましょう!

    いろいろ試していたのでidの数値が大きくなっていますが、ここまで順調に進んでいれば3になっていると思います。

    addUserをした後にusersを叩くと、しっかりと追加されていることが確認できますね!

    まとめ

    ControllerにAPIを実装するのと、そう変わらない手間でGraphQLAPIの作成ができたと思います。

    冒頭で述べたGraphQLの利点以外にも、APIごとに必要なパラメータやレスポンスの型などが、MutationやResolverでわかりやすくなってる点が個人的には好みなところです。

    今回のコードは以下のリポジトリにまとめてありますので、ぜひ確認してみてください!

    https://github.com/ryuto-imai/test_graphql_api

    りゅうちゃん(エンジニア)

    りゅうちゃん(エンジニア)

    おすすめ記事