Ruby
GraphQL
graphql-ruby

graphql-rubyのエラーレスポンスを拡張する

やりたきこと

↓こんな感じのjsonを

{
  "data": {
    ...
  },
  "errors": [
    {
      "message": "何かエラーがあったみたい",
      "locations": [
        {
          "line": 2,
          "column": 7
        }
      ],
      "path": [
        "hogehoge"
      ]
    }
  ]
}

↓こんな感じにしたい

{
  "data": {
    ...
  },
  "errors": [
    {
      "code": "1234",
      "message": "何かエラーがあったみたい"
    }
  ]
}

codeとかkeyとかプログラマブルな何かが欲しい。

やりかた

  1. GraphQL::ExecutionError を継承したエラーclassを作る
  2. to_hメソッドで欲しい情報を返す
  3. resolveの中で作ったエラーをraiseする
my_error.rb
class MyError < GraphQL::ExecutionError
  attr_reader :code

  def initialize(code, message)
    @code = code
    super(message)
  end

  def to_h
    { 'code' => code, 'message' => message }
  end
end
resolve ->(_obj, _args, _ctx) { raise MyError.new('1234', '何かエラーがあったみたい') }

雑記

ドキュメントには特に書いてないので公式的な方法じゃないのかも。良くない方法だったらご指摘ください。。。
読んだソースはこのへん
rescue_fromってのも使えそうかも。ブロックでreturnした値はGraphQL::ExecutionError.newに食われてしまうけど、ブロック内でraiseしたら行けるんじゃないかな。試してない。。。
こんなかんじ?

app/graphql/my_schema.rb
MySchema = GraphQL::Schema.define do
  query QueryType
  mutation MutationType

  rescue_from KyacchiShitaiNannkaNoError do |err|
    raise MyError('1234', err.message)
  end
end

RESTfulに慣れていたのでエラー時にも200を返すのが気持ち悪く感じた。が、「RESTfulじゃないからここにいるのだ」と自分に言い聞かせた。