File: arguments_cache.rb

package info (click to toggle)
ruby-graphql 2.2.17-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 9,584 kB
  • sloc: ruby: 67,505; ansic: 1,753; yacc: 831; javascript: 331; makefile: 6
file content (105 lines) | stat: -rw-r--r-- 4,002 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# frozen_string_literal: true

module GraphQL
  module Execution
    class Interpreter
      class ArgumentsCache
        def initialize(query)
          @query = query
          @dataloader = query.context.dataloader
          @storage = Hash.new do |h, argument_owner|
            args_by_parent = if argument_owner.arguments_statically_coercible?
              shared_values_cache = {}
              Hash.new do |h2, ignored_parent_object|
                h2[ignored_parent_object] = shared_values_cache
              end
            else
              Hash.new do |h2, parent_object|
                args_by_node = {}
                args_by_node.compare_by_identity
                h2[parent_object] = args_by_node
              end
            end
            args_by_parent.compare_by_identity
            h[argument_owner] = args_by_parent
          end
          @storage.compare_by_identity
        end

        def fetch(ast_node, argument_owner, parent_object)
          # This runs eagerly if no block is given
          @storage[argument_owner][parent_object][ast_node] ||= begin
            args_hash = self.class.prepare_args_hash(@query, ast_node)
            kwarg_arguments = argument_owner.coerce_arguments(parent_object, args_hash, @query.context)
            @query.after_lazy(kwarg_arguments) do |resolved_args|
              @storage[argument_owner][parent_object][ast_node] = resolved_args
            end
          end

        end

        # @yield [Interpreter::Arguments, Lazy<Interpreter::Arguments>] The finally-loaded arguments
        def dataload_for(ast_node, argument_owner, parent_object, &block)
          # First, normalize all AST or Ruby values to a plain Ruby hash
          arg_storage = @storage[argument_owner][parent_object]
          if (args = arg_storage[ast_node])
            yield(args)
          else
            args_hash = self.class.prepare_args_hash(@query, ast_node)
            argument_owner.coerce_arguments(parent_object, args_hash, @query.context) do |resolved_args|
              arg_storage[ast_node] = resolved_args
              yield(resolved_args)
            end
          end
          nil
        end

        private

        NO_ARGUMENTS = GraphQL::EmptyObjects::EMPTY_HASH
        NO_VALUE_GIVEN = NOT_CONFIGURED

        def self.prepare_args_hash(query, ast_arg_or_hash_or_value)
          case ast_arg_or_hash_or_value
          when Hash
            if ast_arg_or_hash_or_value.empty?
              return NO_ARGUMENTS
            end
            args_hash = {}
            ast_arg_or_hash_or_value.each do |k, v|
              args_hash[k] = prepare_args_hash(query, v)
            end
            args_hash
          when Array
            ast_arg_or_hash_or_value.map { |v| prepare_args_hash(query, v) }
          when GraphQL::Language::Nodes::Field, GraphQL::Language::Nodes::InputObject, GraphQL::Language::Nodes::Directive
            if ast_arg_or_hash_or_value.arguments.empty? # rubocop:disable Development/ContextIsPassedCop -- AST-related
              return NO_ARGUMENTS
            end
            args_hash = {}
            ast_arg_or_hash_or_value.arguments.each do |arg| # rubocop:disable Development/ContextIsPassedCop -- AST-related
              v = prepare_args_hash(query, arg.value)
              if v != NO_VALUE_GIVEN
                args_hash[arg.name] = v
              end
            end
            args_hash
          when GraphQL::Language::Nodes::VariableIdentifier
            if query.variables.key?(ast_arg_or_hash_or_value.name)
              variable_value = query.variables[ast_arg_or_hash_or_value.name]
              prepare_args_hash(query, variable_value)
            else
              NO_VALUE_GIVEN
            end
          when GraphQL::Language::Nodes::Enum
            ast_arg_or_hash_or_value.name
          when GraphQL::Language::Nodes::NullValue
            nil
          else
            ast_arg_or_hash_or_value
          end
        end
      end
    end
  end
end