I have a script that iterates using ObjectSpace#each_object
with no args. Then it prints how many instances exist for each class.
I realized that some classes redefine the #class
instance method, so I had to find another way to get the actual class; Let's say it's stored in variable "klass"
, and klass === object
is true.
In Ruby 1.8 I could do this, assuming Object
wasn't monkeypatched:
Object.instance_method(:class).bind(object).call
This worked for ActiveSupport::Duration
instances:
# Ruby 1.8
# (tries to trick us)
20.seconds.class
=> Fixnum
# don't try to trick us, we can tell
Object.instance_method(:class).bind(20.seconds).call
=> ActiveSupport::Duration
But, in Ruby 1.9 this no longer works:
# Ruby 1.9
# we are not smart...
Object.instance_method(:class).bind(20.seconds).call
TypeError: bind argument must be an instance of Object
from (irb):53:in `bind'
from (irb):53
from /Users/user/.rvm/rubies/ruby-1.9.2-p0/bin/irb:17:in `<main>'
It turns out that ActiveSupport::Duration
subclasses ActiveSupport::BasicObject
. The latter is made to subclass ::BasicObject
in Ruby 1.9, so Object
is excluded from the inheritance chain. This doesn't, and can't, happen in Ruby 1.8, so ActiveSupport::BasicObject
is a subclass of Object
.
I haven't found any way to detect the actual class of a Ruby 1.9 object that isn't an instance of Object
. BasicObject
in 1.9 is really bare-bones:
BasicObject.instance_methods
=> [:==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__]
Ideas?
UPDATE:
Since ruby 1.9 reached end-of-life, I'm changing my accept to @indirect's answer. The mentions of ruby 1.9 above are merely for historical purposes, to show that the change from 1.8 to 1.9 was the original cause of my problem.
See Question&Answers more detail:
os