Class: GraphQL::Language::Nodes::AbstractNode

Inherits:
Object
  • Object
show all
Defined in:
lib/graphql/language/nodes.rb

Overview

AbstractNode is the base class for all nodes in a GraphQL AST.

It provides some APIs for working with ASTs: - children returns all AST nodes attached to this one. Used for tree traversal. - scalars returns all scalar (Ruby) values attached to this one. Used for comparing nodes. - to_query_string turns an AST node into a GraphQL string

Defined Under Namespace

Modules: DefinitionNode

Constant Summary collapse

NO_CHILDREN =
[].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ AbstractNode

Initialize a node by extracting its position, then calling the class’s initialize_node method.

Parameters:

  • options (Hash) (defaults to: {})

    Initial attributes for this node



28
29
30
31
32
33
34
35
36
37
38
# File 'lib/graphql/language/nodes.rb', line 28

def initialize(options = {})
  if options.key?(:position_source)
    position_source = options.delete(:position_source)
    @line = position_source.line
    @col = position_source.col
  end

  @filename = options.delete(:filename)

  initialize_node(**options)
end

Instance Attribute Details

#colObject (readonly)

Returns the value of attribute col.



23
24
25
# File 'lib/graphql/language/nodes.rb', line 23

def col
  @col
end

#filenameObject (readonly)

Returns the value of attribute filename.



23
24
25
# File 'lib/graphql/language/nodes.rb', line 23

def filename
  @filename
end

#lineObject (readonly)

Returns the value of attribute line.



23
24
25
# File 'lib/graphql/language/nodes.rb', line 23

def line
  @line
end

Class Method Details

.inherited(child_class) ⇒ Object

Add a default #visit_method and #children_method_name using the class name



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/graphql/language/nodes.rb', line 138

def inherited(child_class)
  super
  name_underscored = child_class.name
    .split("::").last
    .gsub(/([a-z])([A-Z])/,'\1_\2') # insert underscores
    .downcase # remove caps

  child_class.module_eval <<-RUBY
    def visit_method
      :on_#{name_underscored}
    end

    def children_method_name
      :#{name_underscored}s
    end
  RUBY
end

Instance Method Details

#childrenArray<GraphQL::Language::Nodes::AbstractNode>

Returns all nodes in the tree below this one.

Returns:



52
53
54
# File 'lib/graphql/language/nodes.rb', line 52

def children
  NO_CHILDREN
end

#delete_child(previous_child) ⇒ Object

TODO DRY with replace_child



115
116
117
118
119
120
121
122
123
124
125
# File 'lib/graphql/language/nodes.rb', line 115

def delete_child(previous_child)
  # Figure out which list `previous_child` may be found in
  method_name = previous_child.children_method_name
  # Copy that list, and delete previous_child
  new_children = public_send(method_name).dup
  new_children.delete(previous_child)
  # Copy this node, but with the new list of children:
  copy_of_self = merge(method_name => new_children)
  # Return the copy:
  copy_of_self
end

#eql?(other) ⇒ Boolean

Value equality

Returns:

  • (Boolean)

    True if self is equivalent to other



42
43
44
45
46
47
# File 'lib/graphql/language/nodes.rb', line 42

def eql?(other)
  return true if equal?(other)
  other.is_a?(self.class) &&
    other.scalars.eql?(self.scalars) &&
    other.children.eql?(self.children)
end

#initialize_copy(other) ⇒ Object

This might be unnecessary, but its easiest to add it here.



62
63
64
65
66
# File 'lib/graphql/language/nodes.rb', line 62

def initialize_copy(other)
  @children = nil
  @scalars = nil
  @query_string = nil
end

#merge(new_options) ⇒ AbstractNode

This creates a copy of self, with new_options applied.

Parameters:

  • new_options (Hash)

Returns:



88
89
90
# File 'lib/graphql/language/nodes.rb', line 88

def merge(new_options)
  dup.merge!(new_options)
end

#positionObject



73
74
75
# File 'lib/graphql/language/nodes.rb', line 73

def position
  [line, col]
end

#replace_child(previous_child, new_child) ⇒ Object

Copy self, but modify the copy so that previous_child is replaced by new_child



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/graphql/language/nodes.rb', line 93

def replace_child(previous_child, new_child)
  # Figure out which list `previous_child` may be found in
  method_name = previous_child.children_method_name
  # Get the value from this (original) node
  prev_children = public_send(method_name)
  if prev_children.is_a?(Array)
    # Copy that list, and replace `previous_child` with `new_child`
    # in the list.
    new_children = prev_children.dup
    prev_idx = new_children.index(previous_child)
    new_children[prev_idx] = new_child
  else
    # Use the new value for the given attribute
    new_children = new_child
  end
  # Copy this node, but with the new child value
  copy_of_self = merge(method_name => new_children)
  # Return the copy:
  copy_of_self
end

#scalarsArray<Integer, Float, String, Boolean, Array>

Returns Scalar values attached to this node.

Returns:

  • (Array<Integer, Float, String, Boolean, Array>)

    Scalar values attached to this node



57
58
59
# File 'lib/graphql/language/nodes.rb', line 57

def scalars
  NO_CHILDREN
end

#to_query_string(printer: GraphQL::Language::Printer.new) ⇒ Object



77
78
79
80
81
82
83
# File 'lib/graphql/language/nodes.rb', line 77

def to_query_string(printer: GraphQL::Language::Printer.new)
  if printer.is_a?(GraphQL::Language::Printer)
    @query_string ||= printer.print(self)
  else
    printer.print(self)
  end
end

#visit_methodSymbol

Returns the method to call on Visitor for this node.

Returns:

  • (Symbol)

    the method to call on Visitor for this node

Raises:



69
70
71
# File 'lib/graphql/language/nodes.rb', line 69

def visit_method
  raise GraphQL::RequiredImplementationMissingError, "#{self.class.name}#visit_method shold return a symbol"
end