class BetterErrors::RaisedException

Attributes

backtrace[R]
exception[R]
hint[R]
message[R]

Public Class Methods

new(exception) click to toggle source
# File lib/better_errors/raised_exception.rb, line 8
def initialize(exception)
  if exception.class.name == "ActionView::Template::Error" && exception.respond_to?(:cause)
    # Rails 6+ exceptions of this type wrap the "real" exception, and the real exception
    # is actually more useful than the ActionView-provided wrapper. Once Better Errors
    # supports showing all exceptions in the cause stack, this should go away. Or perhaps
    # this can be changed to provide guidance by showing the second error in the cause stack
    # under this condition.
    exception = exception.cause if exception.cause
  elsif exception.respond_to?(:original_exception) && exception.original_exception
    # This supports some specific Rails exceptions, and this is not intended to act the same as
    # the Ruby's {Exception#cause}.
    # It's possible this should only support ActionView::Template::Error, but by not changing
    # this we're preserving longstanding behavior of Better Errors with Rails < 6.
    exception = exception.original_exception
  end

  @exception = exception
  @message = exception.message

  setup_backtrace
  setup_hint
  massage_syntax_error
end

Public Instance Methods

type() click to toggle source
# File lib/better_errors/raised_exception.rb, line 32
def type
  exception.class
end

Private Instance Methods

has_bindings?() click to toggle source
# File lib/better_errors/raised_exception.rb, line 37
def has_bindings?
  exception.respond_to?(:__better_errors_bindings_stack) && exception.__better_errors_bindings_stack.any?
end
massage_syntax_error() click to toggle source
# File lib/better_errors/raised_exception.rb, line 71
def massage_syntax_error
  case exception.class.to_s
  when "Haml::SyntaxError", "Sprockets::Coffeelint::Error"
    if /\A(.+?):(\d+)/ =~ exception.backtrace.first
      backtrace.unshift(StackFrame.new($1, $2.to_i, ""))
    end
  when "SyntaxError"
    if /\A(.+?):(\d+): (.*)/m =~ exception.message
      backtrace.unshift(StackFrame.new($1, $2.to_i, ""))
      @message = $3
    end
  end
end
setup_backtrace() click to toggle source
# File lib/better_errors/raised_exception.rb, line 41
def setup_backtrace
  if has_bindings?
    setup_backtrace_from_bindings
  else
    setup_backtrace_from_backtrace
  end
end
setup_backtrace_from_backtrace() click to toggle source
# File lib/better_errors/raised_exception.rb, line 63
def setup_backtrace_from_backtrace
  @backtrace = (exception.backtrace || []).map { |frame|
    if /\A(?<file>.*?):(?<line>\d+)(:in `(?<name>.*)')?/ =~ frame
      StackFrame.new(file, line.to_i, name)
    end
  }.compact
end
setup_backtrace_from_bindings() click to toggle source
# File lib/better_errors/raised_exception.rb, line 49
def setup_backtrace_from_bindings
  @backtrace = exception.__better_errors_bindings_stack.map { |binding|
    if binding.respond_to?(:source_location) # Ruby >= 2.6
      file = binding.source_location[0]
      line = binding.source_location[1]
    else
      file = binding.eval "__FILE__"
      line = binding.eval "__LINE__"
    end
    name = binding.frame_description
    StackFrame.new(file, line, name, binding)
  }
end
setup_hint() click to toggle source
# File lib/better_errors/raised_exception.rb, line 85
def setup_hint
  @hint = ExceptionHint.new(exception).hint
end