Module: ElasticGraph::GraphQL::Schema::Arguments

Defined in:
lib/elastic_graph/graphql/schema/arguments.rb

Overview

A utility module for working with GraphQL schema arguments.

Class Method Summary collapse

Class Method Details

.to_schema_form(args_value, args_owner) ⇒ Object

A utility method to convert the given ‘args_hash` to its schema form. The schema form is the casing of the arguments according to the GraphQL schema definition. For example, consider a case like:

type Query

widgets(orderBy: [WidgetSort!]): [Widget!]!

The GraphQL gem converts all arguments to ruby keyword args style (symbolized, snake_case keys) before passing the args to us, but the ‘orderBy` argument in the schema definition uses camelCase. ElasticGraph was designed to flexibly support whatever casing the schema developer chooses to use but the GraphQL gem’s conversion to keyword args style gets in the way. ElasticGraph needs to receive the arguments in the casing form defined in the schema so that, for example, when it creates a datastore query, it correctly filters on fields according to the casing of the fields in the index.

This utility method converts an args hash back to its schema form (string keys, with the casing from the schema) by using the arg definitions themselves to get the arg names from the GraphQL schema.

Example:

to_schema_form({ order_by: ["size"] }, widgets_field)
  # => { "orderBy" => ["size"] }

The implementation here was taken from a code snippet provided by the maintainer of the GraphQL gem: github.com/rmosolgo/graphql-ruby/issues/2869



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/elastic_graph/graphql/schema/arguments.rb', line 42

def self.to_schema_form(args_value, args_owner)
  # For custom scalar types (such as `_Any` for apollo federation), `args_owner` won't
  # response to `arguments`.
  return args_value unless args_owner.respond_to?(:arguments)

  __skip__ = case args_value
  when Hash, ::GraphQL::Schema::InputObject
    arg_defns = args_owner.arguments.values

    {}.tap do |accumulator|
      args_value.each do |key, value|
        # Note: we could build `arg_defns` into a hash keyed by `keyword`
        # outside of this loop, to give us an O(1) lookup here. However,
        # usually there are a small number of args (e.g 1 or 2, maybe up
        # to 6 in extreme cases) so it's probably likely to be ultimately
        # slower to build the hash, particularly when you account for the
        # extra memory allocation and GC for the hash.
        arg_defn = arg_defns.find do |a|
          a.keyword == key
        end || raise(SchemaError, "Cannot find an argument definition for #{key.inspect} on `#{args_owner.name}`")

        next_owner = arg_defn.type.unwrap
        accumulator[arg_defn.name] = to_schema_form(value, next_owner)
      end
    end
  when Array
    args_value.map { |arg_value| to_schema_form(arg_value, args_owner) }
  else
    # :nocov: -- not sure how to cover this but we want this default branch.
    args_value
    # :nocov:
  end
end