class GraphQL::Backtrace::Table

A class for turning a context into a human-readable table or array

Constants

HEADERS
MAX_COL_WIDTH
MIN_COL_WIDTH

Public Class Methods

new(context, value:) click to toggle source
# File lib/graphql/backtrace/table.rb, line 16
def initialize(context, value))
  @context = context
  @override_value = value
end

Public Instance Methods

to_backtrace() click to toggle source

@return [Array<String>] An array of position + field name entries

# File lib/graphql/backtrace/table.rb, line 27
def to_backtrace
  @to_backtrace ||= begin
    backtrace = rows.map { |r| "#{r[0]}: #{r[1]}" }
    # skip the header entry
    backtrace.shift
    backtrace
  end
end
to_table() click to toggle source

@return [String] A table layout of backtrace with metadata

# File lib/graphql/backtrace/table.rb, line 22
def to_table
  @to_table ||= render_table(rows)
end

Private Instance Methods

build_rows(context_entry, rows:, top: false) click to toggle source

@return [Array] 5 items for a backtrace table (not `key`)

# File lib/graphql/backtrace/table.rb, line 79
def build_rows(context_entry, rows,, top: false)
  case context_entry
  when GraphQL::Query::Context::FieldResolutionContext
    ctx = context_entry
    field_name = "#{ctx.irep_node.owner_type.name}.#{ctx.field.name}"
    position = "#{ctx.ast_node.line}:#{ctx.ast_node.col}"
    field_alias = ctx.ast_node.alias
    rows << [
      "#{position}",
      "#{field_name}#{field_alias ? " as #{field_alias}" : ""}",
      "#{ctx.object.inspect}",
      ctx.irep_node.arguments.to_h.inspect,
      Backtrace::InspectResult.inspect_result(top && @override_value ? @override_value : ctx.value),
    ]

    build_rows(ctx.parent, rows: rows)
  when GraphQL::Query::Context
    query = context_entry.query
    op = query.selected_operation
    if op
      op_type = op.operation_type
      position = "#{op.line}:#{op.col}"
    else
      op_type = "query"
      position = "?:?"
    end
    op_name = query.selected_operation_name
    rows << [
      "#{position}",
      "#{op_type}#{op_name ? " #{op_name}" : ""}",
      "#{query.root_value.inspect}",
      query.variables.to_h.inspect,
      Backtrace::InspectResult.inspect_result(query.context.value),
    ]
  else
    raise "Unexpected get_rows subject #{context_entry.inspect}"
  end
end
render_table(rows) click to toggle source

@return [String]

# File lib/graphql/backtrace/table.rb, line 43
def render_table(rows)
  max = Array.new(HEADERS.length, MIN_COL_WIDTH)

  rows.each do |row|
    row.each_with_index do |col, idx|
      col_len = col.length
      max_len = max[idx]
      if col_len > max_len
        if col_len > MAX_COL_WIDTH
          max[idx] = MAX_COL_WIDTH
        else
          max[idx] = col_len
        end
      end
    end
  end

  table = "".dup
  last_col_idx = max.length - 1
  rows.each do |row|
    table << row.map.each_with_index do |col, idx|
      max_len = max[idx]
      if idx < last_col_idx
        col = col.ljust(max_len)
      end
      if col.length > max_len
        col = col[0, max_len - 3] + "..."
      end
      col
    end.join(" | ")
    table << "\n"
  end
  table
end
rows() click to toggle source
# File lib/graphql/backtrace/table.rb, line 38
def rows
  @rows ||= build_rows(@context, rows: [HEADERS], top: true)
end