I was kidding with metaprogramming in Ruby and I did this code:
class Class def ===(other) other.kind_of?(self) end end class FakeClass def initialize(object) methods.each {|m| eval "undef #{m}" if m.to_sym != :methods } define = proc do |m| eval(<<-END) def #{m}(*a, &b) @object.#{m}(*a, &b) rescue Object raise $!.class, $!.message.gsub("FakeClass", @object.class.to_s), $!.backtrace-[$!.backtrace[-caller.size-1]] end END end object.methods.each {|m| define[m] } def method_missing(name, *a, &b) if @object.methods.include?(name.to_s) define[name] eval "@object.#{name}(*a, &b)" elsif @object.methods.include?("method_missing") eval "@object.#{name}(*a, &b)" else super end rescue Object raise $!.class, $!.message.gsub("FakeClass", @object.class.to_s), $!.backtrace-[$!.backtrace[-caller.size-1]] end @object = object end end
This creates a fake class that mimics a object. Look:
a = FakeClass.new(1) # => 1 a.class # => Fixnum a.methods # => Return all Fixnum methods a + 1 # => 2 (is not a FakeClass) Fixnum === a # => true a.something # => NoMethodError: # undefined method `something' for 1:Fixnum class Fixnum def foo true end end a.foo # => true
The problem is, now I don't know how to know if a object is real or fake. In others words, if #class
returns the true class of the object. Exist some pure ruby way to differentiate?
Think in a scenario where I don't know that FakeClass exist or I don't know what is the name of the FakeClass. It means I can't edit the FakeClass to add a method like #is_fake?
.
PS: I know that a.instance_eval {self}
returns the object (not fake). But it doesn't help to check if a
is fake.