class Pakyow::Error

Base error object.

Attributes

context[RW]
wrapped_exception[RW]

Public Class Methods

build(original_error, message_type = :default, context: nil, **message_values) click to toggle source

Wraps an error in a pakyow error instance, with additional context.

# File lib/pakyow/error.rb, line 19
def build(original_error, message_type = :default, context: nil, **message_values)
  if original_error.is_a?(self)
    original_error
  else
    message = message(message_type, **message_values)
    message = original_error.message if message.empty?
    new(message).tap do |error|
      error.wrapped_exception = original_error
      error.set_backtrace(original_error.backtrace)
      error.context = context
    end
  end
end
new(*) click to toggle source
Calls superclass method
# File lib/pakyow/error.rb, line 57
def initialize(*)
  @context = nil

  super
end
new_with_message(type = :default, **values) click to toggle source

Initialize an error with a particular message.

# File lib/pakyow/error.rb, line 35
def new_with_message(type = :default, **values)
  new(message(type, **values))
end

Private Class Methods

message(type = :default, **values) click to toggle source
# File lib/pakyow/error.rb, line 41
def message(type = :default, **values)
  if @messages.include?(type)
    Support::StringBuilder.new(
      @messages[type]
    ).build(**values)
  else
    ""
  end
end

Public Instance Methods

cause() click to toggle source
Calls superclass method
# File lib/pakyow/error.rb, line 63
def cause
  wrapped_exception || super
end
condensed_backtrace() click to toggle source

Returns the backtrace without any of the framework locations, unless the error originated from the framework. Return value is as an array of strings rather than backtrace location objects.

# File lib/pakyow/error.rb, line 140
def condensed_backtrace
  if project?
    project_backtrace_locations.map { |line|
      line.to_s.gsub(/^#{Pakyow.config.root}\//, "")
    }
  else
    padded_length = backtrace.map { |line|
      Support::Dependencies.library_name(line).to_s.gsub(/^pakyow-/, "")
    }.max_by(&:length).length + 3

    backtrace.map { |line|
      modified_line = Support::Dependencies.strip_path_prefix(line)
      if line.start_with?(Pakyow.config.root)
        "› ".rjust(padded_length) + modified_line
      elsif modified_line.start_with?("ruby")
        "ruby | ".rjust(padded_length) + modified_line.split("/", 3)[2].to_s
      else
        "#{Support::Dependencies.library_name(line).to_s.gsub(/^pakyow-/, "")} | ".rjust(padded_length) + modified_line.split("/", 2)[1].to_s
      end
    }
  end
end
details() click to toggle source
# File lib/pakyow/error.rb, line 75
    def details
      if project? && location = project_backtrace_locations[0]
        message = "`#{(cause || self).class}' occurred on line `#{location.lineno}' of `#{path}':"

        begin
          <<~MESSAGE
            #{message}

            #{indent_as_source(MethodSource.source_helper([path, location.lineno], location.label), location.lineno)}
          MESSAGE
        rescue StandardError
          <<~MESSAGE
            #{message}

                Error parsing source.
          MESSAGE
        end
      elsif location = (cause || self).backtrace_locations.to_a[0]
        library_name = Support::Dependencies.library_name(location.absolute_path)
        library_type = Support::Dependencies.library_type(location.absolute_path)

        occurred_in = if library_type == :pakyow || library_name.start_with?("pakyow-")
          "within the `#{library_name.split("-", 2)[1]}' framework"
        elsif library_type == :gem || library_type == :bundler
          "within the `#{library_name}' gem"
        else
          "somewhere within ruby itself"
        end

        <<~MESSAGE
          `#{(cause || self).class}' occurred outside of your project, #{occurred_in}.
        MESSAGE
      else
        <<~MESSAGE
          `#{(cause || self).class}' occurred at an unknown location.
        MESSAGE
      end
    end
name() click to toggle source
# File lib/pakyow/error.rb, line 67
def name
  Support.inflector.humanize(
    Support.inflector.underscore(
      Support.inflector.demodulize(self.class.name)
    )
  )
end
path() click to toggle source

If the error occurred in the project, returns the relative path to where the error occurred. Otherwise returns the absolute path to where the error occurred.

# File lib/pakyow/error.rb, line 118
def path
  @path ||= if project?
    Pathname.new(
      File.expand_path(project_backtrace_locations[0].absolute_path.to_s)
    ).relative_path_from(
      Pathname.new(Pakyow.config.root)
    ).to_s
  else
    File.expand_path(project_backtrace_locations[0].absolute_path.to_s)
  end
end
project?() click to toggle source

Returns true if the error occurred in the project.

# File lib/pakyow/error.rb, line 132
def project?
  File.expand_path(backtrace[0].to_s).start_with?(Pakyow.config.root)
end

Private Instance Methods

indent_as_code(message) click to toggle source
# File lib/pakyow/error.rb, line 171
def indent_as_code(message)
  message.split("\n").map { |line|
    "    #{line}"
  }.join("\n")
end
indent_as_source(message, lineno) click to toggle source
# File lib/pakyow/error.rb, line 177
def indent_as_source(message, lineno)
  message.split("\n").each_with_index.map { |line, i|
    start = String.new("    #{lineno + i}|")
    if i == 0
      start << "›"
    else
      start << " "
    end
    "#{start} #{line}"
  }.join("\n")
end
project_backtrace_locations() click to toggle source
# File lib/pakyow/error.rb, line 165
def project_backtrace_locations
  (cause || self).backtrace_locations.to_a.select { |line|
    File.expand_path(line.absolute_path.to_s).start_with?(Pakyow.config.root)
  }
end