Class: GraphQL::InternalRepresentation::Node

Inherits:
Object
  • Object
show all
Defined in:
lib/graphql/internal_representation/node.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name:, owner_type:, query:, return_type:, parent:, ast_nodes: [], definitions: []) ⇒ Node

Returns a new instance of Node.



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/graphql/internal_representation/node.rb', line 54

def initialize(
    name:, owner_type:, query:, return_type:, parent:,
    ast_nodes: [],
    definitions: []
  )
  @name = name
  @query = query
  @owner_type = owner_type
  @parent = parent
  @typed_children = nil
  @scoped_children = Hash.new { |h1, k1| h1[k1] = {} }
  @ast_nodes = ast_nodes
  @definitions = definitions
  @return_type = return_type
end

Instance Attribute Details

#ast_nodesArray<Language::Nodes::AbstractNode> (readonly)

Returns AST nodes which are represented by this node.

Returns:



43
44
45
# File 'lib/graphql/internal_representation/node.rb', line 43

def ast_nodes
  @ast_nodes
end

#definitionsArray<GraphQL::Field> (readonly)

Returns Field definitions for this node (there should only be one!).

Returns:

  • (Array<GraphQL::Field>)

    Field definitions for this node (there should only be one!)



46
47
48
# File 'lib/graphql/internal_representation/node.rb', line 46

def definitions
  @definitions
end

#nameString (readonly)

Returns the name this node has in the response.

Returns:

  • (String)

    the name this node has in the response



6
7
8
# File 'lib/graphql/internal_representation/node.rb', line 6

def name
  @name
end

#owner_typeGraphQL::ObjectType

Returns:



9
10
11
# File 'lib/graphql/internal_representation/node.rb', line 9

def owner_type
  @owner_type
end

#parentInternalRepresentation::Node?



52
53
54
# File 'lib/graphql/internal_representation/node.rb', line 52

def parent
  @parent
end

#queryGraphQL::Query (readonly)

Returns:



144
145
146
# File 'lib/graphql/internal_representation/node.rb', line 144

def query
  @query
end

#return_typeGraphQL::BaseType (readonly)

Returns The expected wrapped type this node must return.

Returns:



49
50
51
# File 'lib/graphql/internal_representation/node.rb', line 49

def return_type
  @return_type
end

#scoped_childrenHash<GraphQL::BaseType, Hash<String => Node>> (readonly)

These children correspond closely to scopes in the AST. Keys may be abstract types. They're assumed to be read-only after rewrite is finished because #typed_children is derived from them.

Using #scoped_children during the rewrite step reduces the overhead of reifying abstract types because they're only reified after the rewrite.

Returns:



40
41
42
# File 'lib/graphql/internal_representation/node.rb', line 40

def scoped_children
  @scoped_children
end

Instance Method Details

#==(other) ⇒ Object



83
84
85
86
87
88
89
90
91
92
# File 'lib/graphql/internal_representation/node.rb', line 83

def ==(other)
  other.is_a?(self.class) &&
    other.name == name &&
    other.parent == parent &&
    other.return_type == return_type &&
    other.owner_type == owner_type &&
    other.scoped_children == scoped_children &&
    other.definitions == definitions &&
    other.ast_nodes == ast_nodes
end

#argumentsObject



98
99
100
# File 'lib/graphql/internal_representation/node.rb', line 98

def arguments
  @query.arguments_for(self, definition)
end

#ast_nodeObject



109
110
111
# File 'lib/graphql/internal_representation/node.rb', line 109

def ast_node
  @ast_node ||= ast_nodes.first
end

#deep_merge_node(new_parent, scope: nil, merge_self: true) ⇒ Object

Merge selections from new_parent into self. Selections are merged in place, not copied.



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/graphql/internal_representation/node.rb', line 121

def deep_merge_node(new_parent, scope: nil, merge_self: true)
  if merge_self
    @ast_nodes |= new_parent.ast_nodes
    @definitions |= new_parent.definitions
  end
  scope ||= Scope.new(@query, @return_type.unwrap)
  new_parent.scoped_children.each do |obj_type, new_fields|
    inner_scope = scope.enter(obj_type)
    inner_scope.each do |scoped_type|
      prev_fields = @scoped_children[scoped_type]
      new_fields.each do |name, new_node|
        prev_node = prev_fields[name]
        if prev_node
          prev_node.deep_merge_node(new_node)
        else
          prev_fields[name] = new_node
        end
      end
    end
  end
end

#definitionObject



102
103
104
105
106
107
# File 'lib/graphql/internal_representation/node.rb', line 102

def definition
  @definition ||= begin
    first_def = @definitions.first
    first_def && @query.get_field(@owner_type, first_def.name)
  end
end

#definition_nameObject



94
95
96
# File 'lib/graphql/internal_representation/node.rb', line 94

def definition_name
  definition && definition.name
end

#initialize_copy(other_node) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/graphql/internal_representation/node.rb', line 70

def initialize_copy(other_node)
  super
  # Bust some caches:
  @typed_children = nil
  @definition = nil
  @definition_name = nil
  @ast_node = nil
  # Shallow-copy some state:
  @scoped_children = other_node.scoped_children.dup
  @ast_nodes = other_node.ast_nodes.dup
  @definitions = other_node.definitions.dup
end

#inspectObject



113
114
115
116
117
# File 'lib/graphql/internal_representation/node.rb', line 113

def inspect
  all_children_names = scoped_children.values.map(&:keys).flatten.uniq.join(", ")
  all_locations = ast_nodes.map {|n| "#{n.line}:#{n.col}" }.join(", ")
  "#<Node #{@owner_type}.#{@name} -> #{@return_type} {#{all_children_names}} @ [#{all_locations}] #{object_id}>"
end

#typed_childrenHash<GraphQL::ObjectType, Hash<String => Node>>

Each key is a ObjectType which this selection may be made on. The values for that key are selections which apply to that type.

This value is derived from #scoped_children after the rewrite is finished.

Returns:



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/graphql/internal_representation/node.rb', line 16

def typed_children
  @typed_childen ||= begin
    new_tc = Hash.new { |h, k| h[k] = {} }
    if @scoped_children.any?
      all_object_types = Set.new
      scoped_children.each_key { |t| all_object_types.merge(@query.possible_types(t)) }
      # Remove any scoped children which don't follow this return type
      # (This can happen with fragment merging where lexical scope is lost)
      all_object_types &= @query.possible_types(@return_type.unwrap)
      all_object_types.each do |t|
        new_tc[t] = get_typed_children(t)
      end
    end
    new_tc
  end
end