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
# File 'lib/graphql/language/nodes.rb', line 28

def initialize(options={})
  if options.key?(:position_source)
    position_source = options.delete(:position_source)
    @line, @col = position_source.line_and_column
  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



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/graphql/language/nodes.rb', line 127

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:



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

def children
  NO_CHILDREN
end

#delete_child(previous_child) ⇒ Object

TODO DRY with replace_child



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

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



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

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.



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

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

#merge(new_options) ⇒ AbstractNode

This creates a copy of self, with new_options applied.

Parameters:

  • new_options (Hash)

Returns:



82
83
84
85
86
87
88
# File 'lib/graphql/language/nodes.rb', line 82

def merge(new_options)
  copied_self = dup
  new_options.each do |key, value|
    copied_self.instance_variable_set(:"@#{key}", value)
  end
  copied_self
end

#positionObject



71
72
73
# File 'lib/graphql/language/nodes.rb', line 71

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



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

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



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

def scalars
  NO_CHILDREN
end

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



75
76
77
# File 'lib/graphql/language/nodes.rb', line 75

def to_query_string(printer: GraphQL::Language::Printer.new)
  printer.print(self)
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:

  • (NotImplementedError)


67
68
69
# File 'lib/graphql/language/nodes.rb', line 67

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