💘

GraphQL ruby でEnumの命名を〇〇_Typeにする

2022/10/23に公開

昇降デスクの高さを全く変えない系エンジニアのyosiです。

仕事のレビュー時に調べて特に記事にする予定はなかったのですが、日曜コーディングで再び出くわしたので記事にしておきます。

GraphQLではEnumを定義できて、以下のように書きます。
(ファイルの置き場所を変えてるのでファイルパスとモジュール名は読み替えてください)

app/graphql/types/enums/sort_type.rb
class Types::Enums::SortType < Types::BaseEnum
  value 'ASC', value: :asc
  value 'DESC', value: :desc
end

このEnumは以下のように使えます。
適当なPostTypeが定義してあるものとします。

app/graphql/types/query_type.rb
module Types
  class QueryType < Types::BaseObject
    # 省略

    field :posts, Types::Objects::PostType.connection_type, null: false do
      argument :sort, Types::Enums::SortType, required: false, default_value: :desc
    end

    def posts(sort:)
      Post.order(id: sort)
    end
  end
end

一見これで完了したように思えますが、意図した挙動はしません。

bundle exec rails graphql:schema:jsonでGraphQLスキーマファイルを出力してみましょう。

schema.json
{
  "kind": "ENUM",
  "name": "Sort",
  "description": null,
  "interfaces": null,
  "possibleTypes": null,
  "fields": null,
  "inputFields": null,
  "enumValues": [
    {
      "name": "ASC",
      "description": null,
      "isDeprecated": false,
      "deprecationReason": null
    },
    {
      "name": "DESC",
      "description": null,
      "isDeprecated": false,
      "deprecationReason": null
    }
  ]
},

nameがSortになってしまっていて、クラス名につけた_Typeが削除されてしまっています。

Github api v4のenum一覧を見ても_typeとついたEnumはたくさんあるので仕様的にできないということはなさそうです。

Enumの名前をクラス名とは別に設定する

結論としてはgraphql_nameを指定することで実現できます。

app/graphql/types/enums/sort_type.rb
class Types::Enums::SortType < Types::BaseEnum
+   graphql_name 'SortType'
+ 
  value 'ASC', value: :asc
  value 'DESC', value: :desc
end

bundle exec rails graphql:schema:jsonでGraphQLスキーマファイルを再度確認してみると、nameがちゃんとSortTypeになってるのが確認できます。

schema.json
{
  "kind": "ENUM",
  "name": "SortType",
  "description": null,
  "interfaces": null,
  "possibleTypes": null,
  "fields": null,
  "inputFields": null,
  "enumValues": [
    {
      "name": "ASC",
      "description": null,
      "isDeprecated": false,
      "deprecationReason": null
    },
    {
      "name": "DESC",
      "description": null,
      "isDeprecated": false,
      "deprecationReason": null
    }
  ]
},

まとめと余談

ドキュメントを読んでもこのあたりへの言及がなくてちょっと困ったのですが、ソースコードを読んでいると/lib/graphql/schema/enum.rbに以下のようなコメントがありました。

@param graphql_name [String, Symbol] the GraphQL value for this, usually SCREAMING_CASE

https://github.com/rmosolgo/graphql-ruby/blob/master/lib/graphql/schema/enum.rb

なるほど。

ちなみにSortTypeTypeにすればいいじゃんって一瞬頭によぎったのはあなたと2人だけの秘密です。

Discussion