Class: GraphQL::InternalRepresentation::Node

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

Constant Summary collapse

DEFAULT_TYPED_CHILDREN =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Proc.new { |h, k| h[k] = {} }

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.



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

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:



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

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!)



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

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



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

def name
  @name
end

#owner_typeGraphQL::ObjectType

Returns:



11
12
13
# File 'lib/graphql/internal_representation/node.rb', line 11

def owner_type
  @owner_type
end

#parentInternalRepresentation::Node?



54
55
56
# File 'lib/graphql/internal_representation/node.rb', line 54

def parent
  @parent
end

#queryGraphQL::Query (readonly)

Returns:



146
147
148
# File 'lib/graphql/internal_representation/node.rb', line 146

def query
  @query
end

#return_typeGraphQL::BaseType (readonly)

Returns The expected wrapped type this node must return.

Returns:



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

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:



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

def scoped_children
  @scoped_children
end

Instance Method Details

#==(other) ⇒ Object



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

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



100
101
102
# File 'lib/graphql/internal_representation/node.rb', line 100

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

#ast_nodeObject



111
112
113
# File 'lib/graphql/internal_representation/node.rb', line 111

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.



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

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



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

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

#definition_nameObject



96
97
98
# File 'lib/graphql/internal_representation/node.rb', line 96

def definition_name
  definition && definition.name
end

#initialize_copy(other_node) ⇒ Object



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

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



115
116
117
118
119
# File 'lib/graphql/internal_representation/node.rb', line 115

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

#subscription_topicObject



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/graphql/internal_representation/node.rb', line 148

def subscription_topic
  @subscription_topic ||= begin
    scope = if definition.subscription_scope
      @query.context[definition.subscription_scope]
    else
      nil
    end
    Subscriptions::Event.serialize(
      definition_name,
      @query.arguments_for(self, definition),
      definition,
      scope: scope
    )
  end
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:



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

def typed_children
  @typed_childen ||= begin
    new_tc = Hash.new(&DEFAULT_TYPED_CHILDREN)
    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