ruby の Exception クラスでは、コンストラクタにメッセージを渡すことができる。
e = Exception.new('foo')
puts e.to_s # foo
puts e.message # fooこのメッセージを #instance_variable_get で取得しようとしたのだが取れない。#instance_variables で空配列が返って来る.
e.instance_variables #=> []C の実装を見てみると、どうやらこれは、rb_iv_set の使い方によるもののようだ。
[1] pry(main)> show-source StandardError#initialize
From: error.c (C Method):
Owner: Exception
Visibility: private
Number of lines: 11
static VALUE
exc_initialize(int argc, VALUE *argv, VALUE exc)
{
VALUE arg;
rb_scan_args(argc, argv, "01", &arg);
rb_iv_set(exc, "mesg", arg);
rb_iv_set(exc, "bt", Qnil);
return exc;
}rb_iv_set(exc, "@mesg", arg); ではなく、rb_iv_set(exc, "mesg", arg); になっている。@がないと Ruby からは触れない。残念。
ちなみになぜ、エラーメッセージに触りたかったのかというと、子クラスで Exception#to_s メソッドをオーバーライドしたかったからである。
[3] pry(main)> show-source StandardError#to_s
From: error.c (C Method):
Owner: Exception
Visibility: public
Number of lines: 8
static VALUE
exc_to_s(VALUE exc)
{
VALUE mesg = rb_attr_get(exc, rb_intern("mesg"));
if (NIL_P(mesg)) return rb_class_name(CLASS_OF(exc));
return rb_String(mesg);
}これを少しカスタマイズした以下のような関数を定義したかったのだが、無理でした.という話。Berkshelf に投げたこの pull request に関連する。
def to_s
if @message
@message
else
"Awesome Error Message"
end
endFYI: なお、CRuby のコードは pry-doc gem を入れて追った。
