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

Instance Attribute Details

#filenameObject (readonly)

Returns the value of attribute filename.



34
35
36
# File 'lib/graphql/language/nodes.rb', line 34

def filename
  @filename
end

Class Method Details

.children_of_typeObject



168
169
170
# File 'lib/graphql/language/nodes.rb', line 168

def children_of_type
  @children_methods
end

.inherited(child_class) ⇒ Object

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



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

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



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

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:



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

def children
  NO_CHILDREN
end

#children_method_nameObject



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

def children_method_name
  self.class.children_method_name
end

#colObject



40
41
42
# File 'lib/graphql/language/nodes.rb', line 40

def col
  @col ||= @source&.column_at(@pos)
end

#definition_lineObject



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

def definition_line
  @definition_line ||= (@source && @definition_pos) ? @source.line_at(@definition_pos) : nil
end

#delete_child(previous_child) ⇒ Object

TODO DRY with replace_child



122
123
124
125
126
127
128
129
130
131
132
# File 'lib/graphql/language/nodes.rb', line 122

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.



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

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

#lineObject



36
37
38
# File 'lib/graphql/language/nodes.rb', line 36

def line
  @line ||= @source&.line_at(@pos)
end

#merge(new_options) ⇒ AbstractNode

This creates a copy of self, with new_options applied.

Parameters:

  • new_options (Hash)

Returns:



95
96
97
# File 'lib/graphql/language/nodes.rb', line 95

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

#positionObject



80
81
82
# File 'lib/graphql/language/nodes.rb', line 80

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



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

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



65
66
67
# File 'lib/graphql/language/nodes.rb', line 65

def scalars
  NO_CHILDREN
end

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



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

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