Class: GraphQL::InternalRepresentation::Node

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

Defined Under Namespace

Classes: NoTypedChildren

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] = {} }
NO_TYPED_CHILDREN =
NoTypedChildren.new

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.



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

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:



61
62
63
# File 'lib/graphql/internal_representation/node.rb', line 61

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



64
65
66
# File 'lib/graphql/internal_representation/node.rb', line 64

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



21
22
23
# File 'lib/graphql/internal_representation/node.rb', line 21

def name
  @name
end

#owner_typeGraphQL::ObjectType

Returns:



24
25
26
# File 'lib/graphql/internal_representation/node.rb', line 24

def owner_type
  @owner_type
end

#parentInternalRepresentation::Node?



70
71
72
# File 'lib/graphql/internal_representation/node.rb', line 70

def parent
  @parent
end

#queryGraphQL::Query (readonly)

Returns:



165
166
167
# File 'lib/graphql/internal_representation/node.rb', line 165

def query
  @query
end

#return_typeGraphQL::BaseType (readonly)

Returns The expected wrapped type this node must return.

Returns:



67
68
69
# File 'lib/graphql/internal_representation/node.rb', line 67

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:



58
59
60
# File 'lib/graphql/internal_representation/node.rb', line 58

def scoped_children
  @scoped_children
end

Instance Method Details

#==(other) ⇒ Object



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

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



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

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

#ast_nodeObject



127
128
129
# File 'lib/graphql/internal_representation/node.rb', line 127

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.



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/graphql/internal_representation/node.rb', line 139

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
  new_sc = new_parent.scoped_children
  if new_sc.any?
    scope ||= Scope.new(@query, @return_type.unwrap)
    new_sc.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
end

#definitionObject



120
121
122
123
124
125
# File 'lib/graphql/internal_representation/node.rb', line 120

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

#definition_nameObject



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

def definition_name
  definition && definition.name
end

#initialize_copy(other_node) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/graphql/internal_representation/node.rb', line 88

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



131
132
133
134
135
# File 'lib/graphql/internal_representation/node.rb', line 131

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



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/graphql/internal_representation/node.rb', line 167

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:



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/graphql/internal_representation/node.rb', line 31

def typed_children
  @typed_children ||= begin
    if @scoped_children.any?
      new_tc = Hash.new(&DEFAULT_TYPED_CHILDREN)
      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
      new_tc
    else
      NO_TYPED_CHILDREN
    end

  end
end