【Rails】graphqlでenumを使う方法

バックエンド

はじめに

完全に備忘録です。ドキュメントも用意されています。
最初にenumの使い方を軽く載せてますが、知ってる方は読み飛ばしてください。

使用した環境については以下の記事でセットアップしたものをそのまま使ってます。
特に読んでなくても大丈夫ですが、気になった方はついでに読んでいただけると嬉しいです!

railsのenumについて

こんな感じで使えます。
入りうる値をあらかじめ列挙しておくことができます。可読性が良くなったり、タイポを防げる良い子です、

class CreateTags < ActiveRecord::Migration[7.0]
  def change
    create_table :tags do |t|
      t.integer :type, defalut: 0

      t.timestamps
    end
  end
end
class Tag < ApplicationRecord
  self.inheritance_column = :_type_disabled
  enum type: [:hobby, :living, :job]
end
tag = Tag.first
tag.type = "hobby"
puts tag.type
# => "hobby"
Tag.types
# => {"hobby"=>0, "living"=>1, "job"=>2}

graphql-ruby でEnum

型定義

まずはモデルにenumを定義します。(上で書いたのと同じ内容です。)

class Tag < ApplicationRecord
  self.inheritance_column = :_type_disabled
  enum type: [:hobby, :living, :job]
end

つぎにgraphql-rubyで使うためにenumを型として定義してあげます。

module Types
  module Custom
    class TagTypeEnum < Types::BaseEnum
      value "hobby", "hobby"
      value "living", "living"
      value "job", "job"
    end
  end
end

graphql-rubyのtagオブジェクトのtypeは以下のような感じで書けばOKです。

module Types
  class TagType < Types::BaseObject
    field :type, Types::Custom::TagTypeEnum, null: false
  end
end

Resolverでの使い方

例えばtypeフィールドでレコードを絞り込むResolverを作りたいときは以下のようにできます。

module Resolvers
  class TagsResolver < Resolvers::BaseResolver
    type [Types::TagType], null: false

    argument :type, Types::Custom::TagTypeEnum, required: true

    def resolve(**args)
      Tag.where(type: args[:type])
    end
  end
end

Mutationでの使い方

新しくTagを追加するMutationはこんな感じです。

module Mutations
  class CreateTag < Mutations::BaseMutation
    field :tag, Types::TagType, null: false

    argument :type, Types::Custom::TagTypeEnum, required: true

    def resolve(type:)
      {
        tag: Tag.create!(type: type)
      }
    end
  end
end

クライアントからの使い方

graphiqlではこんな感じ

{
  // "hobby"だとエラーになる(ダブルクォートがいらない)
  tags(type: hobby) {
    id
    type
  }
}

apollo clientから呼ぶときはこんな感じ

const [createTag] = useMutation(gql`
  mutation createTag($input: CreateTagInput!){
    createTag(input: $input){
      tag
    }
  }
`);

createTag({
  variables: {
    input: {
      // jsから呼ぶときは普通に文字列で渡せばOK
      type: "hobby"
    }
  }
})

タイトルとURLをコピーしました