Analyzer APIを使ってconnectionフィールドのfirstまたはlast argumentを必須パラメータにする (graphql-ruby 1.8)
graphql-ruby 1.9向け: Analyzer APIを使ってconnectionフィールドのfirstまたはlast argumentを必須パラメータにする (graphql-ruby 1.9)
https://developer.github.com/v4/guides/resource-limitations/
Clients must supply a first or last argument on any connection.
GitHubのGraphQL APIはconnectionのargumentに対して、firstかlastのいずれかを必ず指定しなければいけないという独自の制約を持たせています。
これと同様の挙動をAnalyzer APIを使って実装できたのでメモしておきます。
https://github.com/y310/class-api-test/commit/9ac09d62a0baf785a44901f30d1b1a6853122049
Analyzer APIはクエリのノードを走査する際に、ノードごとにenter/leave時にコールバックを実行してくれます。
そのため、connectionノードに入ったときに引数にfirstかlastが含まれているかどうかチェックし、どちらもない場合はエラーを返すことで目的を達成することができます。
具体的には以下のような実装になります。
code: ruby
# app/graphql/analyzers/relay_connection_first_last_required.rb
module Analyzers
class RelayConnectionFirstLastRequired
def initial_value(query)
[]
end
def call(errors, visit_type, irep_node)
if first_and_last_missing?(visit_type, irep_node)
errors << GraphQL::AnalysisError.new("You must provide a first or last value to properly paginate the #{irep_node.name} connection.")
end
errors
end
def final_value(errors)
errors
end
def first_and_last_missing?(visit_type, irep_node)
visit_type == :enter &&
connection_node?(irep_node) &&
!has_first_or_last?(irep_node)
end
def connection_node?(irep_node)
irep_node&.definition&.connection?
end
def has_first_or_last?(irep_node)
!(%w(first last) & irep_node.arguments.keys).empty?
end
end
end
# app/graphql/class_api_test_schema.rb
class ClassApiTestSchema < GraphQL::Schema
# (snip)
query_analyzer Analyzers::RelayConnectionFirstLastRequired.new
# (snip)
end
Analyzer APIを使ってconnectionフィールドのfirstまたはlast argumentを必須パラメータにする