Skip to content

Instantly share code, notes, and snippets.

@leandro
Created April 5, 2023 13:28
Show Gist options
  • Save leandro/fbd8e5f3d58a3e1293a5aa17452f2104 to your computer and use it in GitHub Desktop.
Save leandro/fbd8e5f3d58a3e1293a5aa17452f2104 to your computer and use it in GitHub Desktop.
Retrieving the queried fields from a GraphQL operation request (when using `graphql-ruby` gem)
module Graphql
class Utils
CONTEXT_CLASS = GraphQL::Query::Context
FIELD_CLASS = GraphQL::Language::Nodes::Field
FRAGMENT_CLASS = GraphQL::Language::Nodes::FragmentSpread
# Given a GraphQL context (literally, the +context+ method from inside any GraphQL field
# method), this method will return all the fields requested in the operation request.
# So, considering the following query example:
#
# query pipelinesWithStagesForSelect {
# pipelines {
# id
# name
# stages {
# id
# name
# order
# color
# }
# }
# }
#
# This method will return the following array:
#
# [
# "pipelines.id",
# "pipelines.name",
# "pipelines.stages.id",
# "pipelines.stages.name",
# "pipelines.stages.order",
# "pipelines.stages.color"
# ]
#
def self.query_fields(object, fields_path = [], context = object)
collection_from(object, context).flat_map do |field|
next unless field?(field) || fragment?(field)
next if field.name == '__typename'
children = collection_from(field, context).presence
field_name = field.name.underscore
next_path = fields_path + (fragment?(field) ? [] : [field_name])
children && query_fields(field, next_path, context) || next_path.join('.')
end.compact
end
class << self
private
def context?(object) = object.is_a?(CONTEXT_CLASS)
def field?(object) = object.is_a?(FIELD_CLASS)
def fragment?(object) = object.is_a?(FRAGMENT_CLASS)
def collection_from(object, context)
return object.children if field?(object)
return context.query.fragments[object.name].children if fragment?(object)
object.query.selected_operation.children if context?(object)
end
end
end
end
module Types
module Queries
module PipelineQueryType
include Base
def pipelines
fields = Graphql::Utils.query_fields(context)
Pipelines::List.call(firm: current_firm, queried_fields: fields).pipelines
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment