class GraphQL::Language::Visitor

Depth-first traversal through the tree, calling hooks at each stop.

@example Create a visitor, add hooks, then search a document

total_field_count = 0
visitor = GraphQL::Language::Visitor.new(document)
# Whenever you find a field, increment the field count:
visitor[GraphQL::Language::Nodes::Field] << ->(node) { total_field_count += 1 }
# When we finish, print the field count:
visitor[GraphQL::Language::Nodes::Document].leave << ->(node) { p total_field_count }
visitor.visit
# => 6

Constants

SKIP

If any hook returns this value, the {Visitor} stops visiting this node right away

Public Class Methods

new(document) click to toggle source
# File lib/graphql/language/visitor.rb, line 20
def initialize(document)
  @document = document
  @visitors = {}
end

Private Class Methods

apply_hooks(hooks, node, parent) click to toggle source

If one of the visitors returns SKIP, stop visiting this node

# File lib/graphql/language/visitor.rb, line 63
def self.apply_hooks(hooks, node, parent)
  hooks.reduce(true) { |memo, proc| memo && (proc.call(node, parent) != SKIP) }
end

Public Instance Methods

[](node_class) click to toggle source

Get a {NodeVisitor} for `node_class` @param node_class [Class] The node class that you want to listen to @return [NodeVisitor]

@example Run a hook whenever you enter a new Field

visitor[GraphQL::Language::Nodes::Field] << ->(node, parent) { p "Here's a field" }
# File lib/graphql/language/visitor.rb, line 31
def [](node_class)
  @visitors[node_class] ||= NodeVisitor.new
end
visit() click to toggle source

Visit `document` and all children, applying hooks as you go @return [void]

# File lib/graphql/language/visitor.rb, line 37
def visit
  visit_node(@document, nil)
end

Private Instance Methods

begin_visit(node, parent) click to toggle source
# File lib/graphql/language/visitor.rb, line 51
def begin_visit(node, parent)
  node_visitor = self[node.class]
  self.class.apply_hooks(node_visitor.enter, node, parent)
end
end_visit(node, parent) click to toggle source

Should global `leave` visitors come first or last?

# File lib/graphql/language/visitor.rb, line 57
def end_visit(node, parent)
  node_visitor = self[node.class]
  self.class.apply_hooks(node_visitor.leave, node, parent)
end
visit_node(node, parent) click to toggle source
# File lib/graphql/language/visitor.rb, line 43
def visit_node(node, parent)
  begin_hooks_ok = begin_visit(node, parent)
  if begin_hooks_ok
    node.children.each { |child| visit_node(child, node) }
  end
  end_visit(node, parent)
end