class BetterErrors::ErrorPage

@private

Constants

VariableInfo

Attributes

env[R]
exception[R]
repls[R]

Public Class Methods

new(exception, env) click to toggle source
# File lib/better_errors/error_page.rb, line 31
def initialize(exception, env)
  @exception = RaisedException.new(exception)
  @env = env
  @start_time = Time.now.to_f
  @repls = []
end
render_template(template_name, locals) click to toggle source
# File lib/better_errors/error_page.rb, line 20
def self.render_template(template_name, locals)
  locals.send(:eval, self.template(template_name).src)
rescue => e
  # Fix the backtrace, which doesn't identify the template that failed (within Better Errors).
  # We don't know the line number, so just injecting the template path has to be enough.
  e.backtrace.unshift "#{self.template_path(template_name)}:0"
  raise
end
template(template_name) click to toggle source
# File lib/better_errors/error_page.rb, line 16
def self.template(template_name)
  Erubi::Engine.new(File.read(template_path(template_name)), escape: true)
end
template_path(template_name) click to toggle source
# File lib/better_errors/error_page.rb, line 12
def self.template_path(template_name)
  File.expand_path("../templates/#{template_name}.erb", __FILE__)
end

Private Class Methods

html_formatted_code_block(frame) click to toggle source
# File lib/better_errors/error_page.rb, line 130
def self.html_formatted_code_block(frame)
  CodeFormatter::HTML.new(frame.filename, frame.line).output
end
inspect_value(obj) click to toggle source
# File lib/better_errors/error_page.rb, line 142
def self.inspect_value(obj)
  if BetterErrors.ignored_classes.include? obj.class.name
    "<span class='unsupported'>(Instance of ignored class. "\
    "#{obj.class.name ? "Remove #{CGI.escapeHTML(obj.class.name)} from" : "Modify"}"\
    " BetterErrors.ignored_classes if you need to see it.)</span>"
  else
    InspectableValue.new(obj).to_html
  end
rescue BetterErrors::ValueLargerThanConfiguredMaximum
  "<span class='unsupported'>(Object too large. "\
    "#{obj.class.name ? "Modify #{CGI.escapeHTML(obj.class.name)}#inspect or a" : "A"}"\
    "djust BetterErrors.maximum_variable_inspect_size if you need to see it.)</span>"
rescue Exception => e
  "<span class='unsupported'>(exception #{CGI.escapeHTML(e.class.to_s)} was raised in inspect)</span>"
end
text_formatted_code_block(frame) click to toggle source
# File lib/better_errors/error_page.rb, line 134
def self.text_formatted_code_block(frame)
  CodeFormatter::Text.new(frame.filename, frame.line).output
end

Public Instance Methods

action_dispatch_action_endpoint() click to toggle source
# File lib/better_errors/error_page.rb, line 94
def action_dispatch_action_endpoint
  return unless defined?(ActionDispatch::ActionableExceptions)

  ActionDispatch::ActionableExceptions.endpoint
end
active_support_actions() click to toggle source
# File lib/better_errors/error_page.rb, line 88
def active_support_actions
  return [] unless defined?(ActiveSupport::ActionableError)

  ActiveSupport::ActionableError.actions(exception.type)
end
application_frames() click to toggle source
# File lib/better_errors/error_page.rb, line 100
def application_frames
  backtrace_frames.select(&:application?)
end
backtrace_frames() click to toggle source
# File lib/better_errors/error_page.rb, line 72
def backtrace_frames
  exception.backtrace
end
do_eval(opts) click to toggle source
# File lib/better_errors/error_page.rb, line 59
def do_eval(opts)
  index = opts["index"].to_i
  code = opts["source"]

  unless (binding = backtrace_frames[index].frame_binding)
    return { error: "REPL unavailable in this stack frame" }
  end

  @repls[index] ||= REPL.provider.new(binding, exception)

  eval_and_respond(index, code)
end
do_variables(opts) click to toggle source
# File lib/better_errors/error_page.rb, line 52
def do_variables(opts)
  index = opts["index"].to_i
  frame = backtrace_frames[index]
  variable_info = VariableInfo.new(frame, editor_url(frame), rails_params, rack_session, Time.now.to_f)
  { html: self.class.render_template("variable_info", variable_info) }
end
exception_hint() click to toggle source
# File lib/better_errors/error_page.rb, line 84
def exception_hint
  exception.hint
end
exception_message() click to toggle source
# File lib/better_errors/error_page.rb, line 80
def exception_message
  exception.message.strip.gsub(/(\r?\n\s*\r?\n)+/, "\n")
end
exception_type() click to toggle source
# File lib/better_errors/error_page.rb, line 76
def exception_type
  exception.type
end
first_frame() click to toggle source
# File lib/better_errors/error_page.rb, line 104
def first_frame
  application_frames.first || backtrace_frames.first
end
id() click to toggle source
# File lib/better_errors/error_page.rb, line 38
def id
  @id ||= SecureRandom.hex(8)
end
render_main(csrf_token, csp_nonce) click to toggle source
# File lib/better_errors/error_page.rb, line 42
def render_main(csrf_token, csp_nonce)
  frame = backtrace_frames[0]
  first_frame_variable_info = VariableInfo.new(frame, editor_url(frame), rails_params, rack_session, Time.now.to_f)
  self.class.render_template('main', binding)
end
render_text() click to toggle source
# File lib/better_errors/error_page.rb, line 48
def render_text
  self.class.render_template('text', binding)
end

Private Instance Methods

editor_url(frame) click to toggle source
# File lib/better_errors/error_page.rb, line 110
def editor_url(frame)
  BetterErrors.editor.url(frame.filename, frame.line)
end
eval_and_respond(index, code) click to toggle source
# File lib/better_errors/error_page.rb, line 158
def eval_and_respond(index, code)
  result, prompt, prefilled_input = @repls[index].send_input(code)

  {
    highlighted_input: Rouge::Formatters::HTML.new.format(Rouge::Lexers::Ruby.lex(code)),
    prefilled_input:   prefilled_input,
    prompt:            prompt,
    result:            result
  }
end
rack_session() click to toggle source
# File lib/better_errors/error_page.rb, line 114
def rack_session
  env['rack.session']
end
rails_params() click to toggle source
# File lib/better_errors/error_page.rb, line 118
def rails_params
  env['action_dispatch.request.parameters']
end
request_path() click to toggle source
# File lib/better_errors/error_page.rb, line 126
def request_path
  env["PATH_INFO"]
end
text_heading(char, str) click to toggle source
# File lib/better_errors/error_page.rb, line 138
def text_heading(char, str)
  str + "\n" + char*str.size
end
uri_prefix() click to toggle source
# File lib/better_errors/error_page.rb, line 122
def uri_prefix
  env["SCRIPT_NAME"] || ""
end