Rails
GraphQL
apollo
graphql-ruby
apollo-upload-client

apollo-client v2 + rails (graphql-ruby) でファイルをアップロードするmutationを作る方法

問題

  1. apollo-client v2 でも現状はファイルをアップロードするmutationをカバーしていない?様子
  2. https://github.com/jaydenseric/apollo-upload-client を使う事でファイルアップロードするmutationを作る事は可能
  3. しかしながらファイルがアップロードされる場合、サーバー(今回rails + graphql-ruby)で想定しているparamsの内容とは合っていないのでそのままではファイルを受け取れない
# fileをアップロードしない場合のキー
# app/controllers/graphql_controller.rb
def execute
  params.keys
=> ["query",
 "variables",
 "controller",
 "action",
 "graphql"]
# fileをアップロード**する**場合のキー
# app/controllers/graphql_controller.rb
def execute
  params.keys
=> ["operations",
 "map",
 "0",
 "controller",
 "action"]

解決方法

ネストされた状態などを考えると色々ややこしそうなのでgem化した
https://github.com/github0013/graphql_apollo_upload_client_params

class GraphqlController < ApplicationController

  def execute
    # paramsを使いやすいように加工する
    converted_params = GraphqlApolloUploadClientParams.convert(params)

    variables = converted_params.variables
    query = converted_params.query
    operation_name = converted_params.operation_name

そうしてclient側から通常通りmutationを呼び出して、

  1. variables直下
  2. ネストした中のオブジェクトのプロパティとして
  3. 配列として
  4. FileListのまま

アップロードするファイルオブジェクトを渡す

mutation($file: File!) {
  testField(file: $file)
}
...
...

this.props
.mutate({
  variables: {
    file: fileObject
  }
})
.then(({ data }) => {
  console.log(data)
})

ファイルを受け取るためにはサーバー側で該当mutationのパラメータータイプを独自のFileスカラーにする

FileType = GraphQL::ScalarType.define do
  name "File"
  description "ActionDispatch::Http::UploadedFile"

  coerce_input ->(action_dispatch_uploaded_file, ctx) {
    action_dispatch_uploaded_file
  }
end

あとは通常通りパラメーターとしてファイルが参照できる。