views:

76

answers:

4

I'm trying to make a proxy object that transfers almost all method calls to a child object, essentially the delegator pattern. For the most part, I'm just using a BasicObject and passing every call with method_missing to the child object. So far, so good.

The trick is that try as I might, I can't fool Ruby's case operator, so I can't do:

x = Proxy.new(15)
Fixnum === x #=> false, no matter what I do

This of course makes any case x operations fail, which means the proxies can't be handed off safely to other libraries.

I can't for the life of me figure out what === is using. The proxy works fine for all of the class-based introspection I know of, which is all correctly passed to the child object:

x.is_a?(Fixnum) #=> true
x.instance_of?(Fixnum) #=> true
x.kind_of?(Fixnum) #=> true
x.class #=> Fixnum

Is Module#=== just doing some kind of magic that can't be avoided?

+1  A: 

Yeah, it is. Module#=== is implemented in C, examining the object's class hierarchy directly. It doesn't look like there's a way to fool it.

mkarasek
Thanks. What ennui this brings.
bhuga
A: 
guns
The technical behavior is correct only if you assume that there is a form of object introspection unavailable to the programmer, which, it seems, there is--in C. Unfortunately this proxy needs to track any kind of object, not just Fixnums, so extending really doesn't help (and for various reasons, extending Object is also not useful).
bhuga
Well, I see your point. You would hope that :=== is implemented to `send :instance_of?, MyClass` to your proxy object, but that is in fact not the case. I still maintain though that if you are trying to masquerade as an object, but want some kind of meta-functionality, creating a Tracking class that decorates and tracks individual objects is a better design. Non-singleton objects can be extended, and singleton instances (Fixnum and Symbol for instance) can be wrapped and extended, or specically handled.
guns
A: 

The problem is that it does Fixnum === x, which means that the method === is called on Fixnum and not on x. You could replace all === methods in existence, (and also watch for when new === methods are introduced), but that would be a lot of work, and quite fragile.

grddev
A: 

Hi, you should probably do a search for the BlankSlate class. This class strips out most of the methods from a normal Object and the website has an example of a simple Proxy class that will print out all methods being called. This shoul give you a better picture of what is happening. Sorry I can't give you a fuller answer but I'm on my phone. Hope that helps.

Joc