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 =
GraphQL::EmptyObjects::EMPTY_ARRAY

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



30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/graphql/language/nodes.rb', line 30

def initialize(options = {})
  if options.key?(:position_source)
    position_source = options.delete(:position_source)
    @line = position_source[1]
    @col = position_source[2]
  else
    @line = options.delete(:line)
    @col = options.delete(:col)
  end

  @filename = options.delete(:filename)

  initialize_node(**options)
end

Instance Attribute Details

#colObject (readonly)

Returns the value of attribute col.



25
26
27
# File 'lib/graphql/language/nodes.rb', line 25

def col
  @col
end

#filenameObject (readonly)

Returns the value of attribute filename.



25
26
27
# File 'lib/graphql/language/nodes.rb', line 25

def filename
  @filename
end

#lineObject (readonly)

Returns the value of attribute line.



25
26
27
# File 'lib/graphql/language/nodes.rb', line 25

def line
  @line
end

Class Method Details

.children_of_typeObject



165
166
167
# File 'lib/graphql/language/nodes.rb', line 165

def children_of_type
  @children_methods
end

.inherited(child_class) ⇒ Object

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



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/graphql/language/nodes.rb', line 142

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, __FILE__, __LINE__
    def visit_method
      :on_#{name_underscored}
    end

    class << self
      attr_accessor :children_method_name

      def visit_method
        :on_#{name_underscored}
      end
    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



47
48
49
50
51
52
# File 'lib/graphql/language/nodes.rb', line 47

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:



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

def children
  NO_CHILDREN
end

#children_method_nameObject



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

def children_method_name
  self.class.children_method_name
end

#delete_child(previous_child) ⇒ Object

TODO DRY with replace_child



119
120
121
122
123
124
125
126
127
128
129
# File 'lib/graphql/language/nodes.rb', line 119

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.



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

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:



92
93
94
# File 'lib/graphql/language/nodes.rb', line 92

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

#positionObject



77
78
79
# File 'lib/graphql/language/nodes.rb', line 77

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



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/graphql/language/nodes.rb', line 97

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



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

def scalars
  NO_CHILDREN
end

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



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

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