🐥
GraphQL Rubyにおけるmutationのひと工夫
はじめに
GraphQL Rubyにおいて、rails generate graphql:install
を実行して、生成されるBaseMutationはGraphQL::Schema::RelayClassicMutation
のサブクラスです。
そして、このクラスでは、argumentを定義すると、まとめられたinputが自動生成されます。
ただ、moduleを切ったときには、ひと工夫が必要になります。
Inputの自動生成
例えば、Userを作成するMutationを以下のようにします。
mutations/user_create.rb
module Mutations
class UserCreate < BaseMutation
field :user, Types::Objects::UserType, null: false
argument :email, String
argument :password, String
argument :first_name, String
argument :last_name, String
def resolve(**args)
end
end
end
生成されるInputをこのようになります。
schema.graphql
"""
Autogenerated input type of UserCreate
"""
input UserCreateInput {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
email: String!
firstName: String!
lastName: String!
password: String!
}
名前空間を分けることによる問題
ファイル数が増えてくると、見通しが悪くなるので、ディレクトリを分けたくなります。
ただ、単純にmoduleをきるだけでは生成されるInputは意図したものにはなりません。
mutations/users/create.rb
module Mutations
+ module Users
+ class Create < BaseMutation
end
end
end
この場合、生成されるInputをこのようになります。
schema.graphql
"""
Autogenerated input type of Create
"""
input CreateInput {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
email: String!
firstName: String!
lastName: String!
password: String!
}
CreateInputというシンプルな名前になってしまいました。
これだと、ほかにもCreateクラスが合った場合に自動生成されると上書きされてしまうという問題があります。
解決策
上記の問題を解決するのは、たった一行追加するだけです。
それは graphql_name
です。
mutations/users/create.rb
module Mutations
module Users
class Create < BaseMutation
+ graphql_name('UserCreate')
これで生成されるInputは最初のものと同じになります。
schema.graphql
"""
Autogenerated input type of UserCreate
"""
input UserCreateInput {
"""
A unique identifier for the client performing the mutation.
"""
clientMutationId: String
email: String!
firstName: String!
lastName: String!
password: String!
}
GraphQL Rubyのコードでいうとこの部分になります。
Addition
moduleから命名をいい感じにするクラスメソッドを一つBaseクラスに作ると便利です。
mutations/base_mutation.rb
module Mutations
class BaseMutation < GraphQL::Schema::RelayClassicMutation
# ex) Mutations::Users::CreateをUserCreateにする
def self.build_graphql_name
name.split('::').drop(1).map(&:singularize).join('')
end
end
end
mutations/users/create.rb
module Mutations
module Users
class Create < BaseMutation
+ graphql_name(build_graphql_name) # UserCreate
Discussion