If I have an instance of StandardError, where is the message stored?
s = StandardError.new("hi")
s.message # => "hi"
s.instance_variables # => []
s.instance_variable_get(:@message) # => nil
s.inspect # => "#<StandardError: hi>"
In addition, be mindful that not all parts of Ruby are written in Ruby, especially for very base classes like Exception or StandardError.
You can find your answer by looking at the source of the message method on Exception class (click then go to the message method and use the small magnifying glass to show the source). This code is C, not Ruby.
After some investigation into Ruby and C, I have found that the exception class sets an instance variable with the name of mesg
. This cannot be accessed in the standard Ruby runtime because it does not start with an @
.
It is possible to add a Ruby extension which will let you get and set instance variables that are not prefixed with @
. I have no idea how dangerous this might be.
C Module:
#include "ruby.h"
static VALUE rb_mIvar;
static VALUE rb_ivar_iv_get(VALUE self, VALUE key) {
return rb_ivar_get(self, rb_to_id(key));
}
static VALUE rb_ivar_iv_set(VALUE self, VALUE key, VALUE value) {
return rb_ivar_set(self, rb_to_id(key), value);
}
void Init_ivar() {
rb_mIvar = rb_define_module("Ivar");
rb_define_method(rb_mIvar, "ivar_get", rb_ivar_iv_get, 1);
rb_define_method(rb_mIvar, "ivar_set", rb_ivar_iv_set, 2);
}
Ruby usage:
$:.unshift('.')
require 'ivar'
Object.send(:include, Ivar)
e = StandardError.new("foo")
puts "Error message is: #{e.message}" # => e.message is "foo"
e.ivar_set(:mesg, "bar")
puts "Error message is: #{e.message}" # => e.message is now "bar"
See this gist with the full code I used to research and experiment: https://gist.github.com/adamhunter/5041075
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With