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


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

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

    class << self
      attr_accessor :children_method_name
    end
    self.children_method_name = :#{name_underscored}s
  RUBY
end

Instance Method Details

#==(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 ==(other)
  return true if equal?(other)
  other.kind_of?(self.class) &&
    other.scalars == self.scalars &&
    other.children == self.children
end

#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

#children_method_nameObject


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

def children_method_name
  self.class.children_method_name
end

#delete_child(previous_child) ⇒ Object

TODO DRY with replace_child


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

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

#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:


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

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

#positionObject


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

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


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

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


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

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