3

ブロック内で発生するすべての例外の前にデバッグ情報を追加する必要がありますが、バックトレースを台無しにしたくありません。$!1.9.3ではこれを許可していないようです。raise私が何をしようとしても、バックトレースを置き換えています。

アイデア?

これが私が最初に使用していたものです:

def self.load(filename, virtual_path = nil)
  t = Template.new(filename, virtual_path)
  t.is_page? ? Page.new(t) : t
rescue
  raise $!, "Error loading template '#{filename}'#{virtual_path ? " under virtual path '" + virtual_path  + "'" : ""}: #{$!}"
end

私がこれまでに見つけた最高のものはこれです:

def self.load(filename, virtual_path = nil)
  t = Template.new(filename, virtual_path)
  t.is_page? ? Page.new(t) : t
rescue => e
    raise e, "Error loading template '#{filename}'#{virtual_path ? " under virtual path '" + virtual_path  + "'" : ""}: #{e.message} #{e.backtrace}"
end

これにより、元のスタックトレースがメッセージにダンプされますが、古いスタックトレースはスタックトレースとして保持されません。

4

1 に答える 1

4

Kernel#raiseメソッドを見ると、次の3 つのパラメーターを使用できます。

raise(exception [, string [, array]])

バックトレースを保持したい場合arrayは、コールバック情報であるパラメーターを指定する必要があります。

例:

あなたがもともと持っていたとしましょう:

def some_method()
    raise('original message')
end

some_method
#=> scratch.rb:10:in `some_method': original message (RuntimeError)
#   from scratch.rb:16:in `<main>'

例外の 3 番目のパラメーターを使用して、更新されたメッセージと同じバックトレースで新しい例外を発生させることができます。

def some_method()
    begin
        raise('error message')
    rescue
        raise $!, 'new message', $!.backtrace
    end
end

some_method
#=> scratch.rb:10:in `some_method': new message (RuntimeError)
#       from scratch.rb:16:in `<main>'

ご覧のとおり、新しい例外は元の例外と同じですが、メッセージが更新されています。

于 2013-03-13T13:07:27.870 に答える