How to identify attribute reader methods

Hello world,

I’m currently working with the ‘johnson’ gem (a project that embeds
Mozilla’s spider/trace monkey JavaScript engine in Ruby) on Ruby 1.9 and
encountered the compatibility issue outlined below.

Among other cool features, johnson uses proxies for Ruby objects in
JavaScript (and vice-versa), to allow for things like:

> A = { attr_accessor :a; def f(x); x; end }
> js['a'] =
> js.evaluate("var y = 42")
> js.evaluate("a.f(y)")

This (contrived) example assigns a Ruby object to a JavaScript variable
(‘a’) and calls a method on the object. More to the point, you can also
return the method object from JavaScript land by leaving of the
parentheses just as with regular JavaScript functions:

> js.evaluate("a.f")
=> #<Method: A#f>

Now, johnson tries to treat Ruby instance variables (and attribute
readers) like JavaScript object properties, so instead of a method
object, ideally js.evaluate("a.a") ought to return nil (because the
instance variable @a has not been set and ‘a’ is strictly an attribute
reader defined by attr_accessor). This was achieved in the Johnson code
by using the Data_Get_Struct macro to get the METHOD struct and
subsequently check its node type in the struct’s ‘body’ member like

METHOD* method;
Data_Get_Struct(rb_method, METHOD, method);
if (method && nd_type(method->body) == NODE_IVAR) {
  return Qtrue;

(For this to work, the required definitions were copied from method.h to
the johnson sources).

This fails in 1.9 because the METHOD struct has changed considerably
since 1.8. and I wonder how something similar could be achieved in 1.9.
Is the method type VM_METHOD_TYPE_IVAR in rb_method_definition_t used to
distinguish attribute readers?

Or, to put my question more generally, is there an easy way to check for
reader-type methods from Ruby or from a C extension without having to
resort to internal structs which are not exported by default? That is to
say, when you have a Method object, is there a way to check whether or
not it was originally created by the attr_accessor or attr_reader