Ruby IntelliSense – scoping fun
I’ve just been fine tuning Steel to handle some of the more obscure Ruby syntax. There’s quite a bit of really obscure stuff that you probably wouldn’t come across in the normal run of things. But if you are debugging IntelliSense then you’ve got to be prepared for some wierd syntax.
Here, I’ve declared a class X which encloses a class Y which in turn encloses a class Z. Each class has a singleton (or class method) and an ordinary method. So the question is – what does a good IntelliSense system return under a number of conditions. Here’s the first:
a = X::Y.new - this creates a new object a of type Y.
You can see that the scope resolution operator :: picks out the interior class Y and creates a new Y object. We only get y2 displayed by IntelliSense because y1 is a class singleton.
But then I thought – what happens if I do this:
c = X::Y::Z
Hmmm … well, it is legal Ruby, but it does to my mind drive a coach and horses through the idea that all class names are constants. In this case, c is a local variable. In fact, it turns out that c is the class Z - not of type Z. This comes about because when you declare a class using the class X… construct, you are actually creating an object whose name is X and whose class is Class – and not as you might think, X. So in effect, the lower case c bypasses the requirement of having to use a constant as a class name.
Here’s what you get Notice the class singleton z1 displayed along with the normal ‘class’ methods new, etc. This works because c is an object and so can have singleton methods.
Now if we look at the results shown by creating a Z object from the object c:
d = c.new
we get the correct result shown below. Note: the base object methods have been suppressed for clarity.