OK, so I've worked my way through the Pickaxe Book. Where now? Time to read some real world code and see how Ruby gets used in the wild. First idiom is one i've read about before on Ola's blog, but didn't really "get". It appears right at the start of Why's Camping framework:
We'll ignore the surrounding class and method for the moment. What does the semi cryptic "class <<self; self end" bit do? Well, Pickaxe will tell us that the "class <<obj" notation says "build me a new class just for object obj". This is called an Anonymous or Singleton Class.
Lets rewind. Firstly, remember that every object in Ruby has a class associated with it. It's in the class where the object's methods are stored so it's pretty important - when you invoke a method on an object, Ruby looks for the object's class first and sees if it has the method it needs.
Got it? Now a bit of additional complexity. Classes are objects too. This means that a class can have a class of its own. This isn't it's Super Class. Oh no, we'll get to them in a moment. A classes class is a Virtual Class, (indicated in the diagram below by the 'V' flag) and is the place where all the magic behind Ruby's open classes comes from. If you add a new method "blogMe" to the class "Movie", a new virtual class for the Movie class object is created and that's where your "blogMe" lives. Pickaxe shows these virtual Meta Classes as the classname with a ' appended to the name:
Still with me? Remember too that classes are special objects - they also have Super Classes. This includes virtual classes (see how in the diagram above, they both have the "super" attribute). This is how we get our class hierarchy. If the Ruby interpreter is trying to invoke a method on an object and it doesn't find it on the object's class or virtual class, it'll look at the classes superclass to see what it has to offer. Nae luck? If the superclass has a super class, look there and just keep going...
How do virtual classes methods fit into this hierarchy? Remember a virtual class is a class of an object - the class. It gets checked after a classes methods are checked, but before going up to a classes superclass. Confused? Hopefully not.
So how do we bring Singleton / Anonymous Classes into this? Well, they're a new class, tied to a particular object and inserted between the object and it's real class. Its referred to as a "singleton"because it is class-like, but exists only for the object which created it. Its "anonymous" because it has no name. Indeed, the Pickaxe book uses the Singleton terminology and shows it in diagrams labeled "virtual" and with no name at all.
!!Potential Confusion Warning!!: Some folks wrongly refer to Singleton classes as "Meta Classes". This confused folks so much that there is a special note in Pickaxe to help you out. As they state, Ruby does have Meta Classes, but they are different from Smalltalk because Singletons are not a class of a class; they are a singleton class of a class
So what can we do with all this? Well, because we now have a class which exists solely for the object which created it, we can do things like addign methods to that object and that object alone. This is what Why? is doing in the code clip:
He's wrapped it up all nice for us in a method called meta_def (which is available to all objects which are of class Object - that's a lot). It takes two parameters which are 'm', the name for the new method, and '&b he creates a ', the block which will be the body of the new method. Once in the method, new Singleton class for the object which called the method, and then creates the method on the new singleton using the :define_method method and we're done.
Short. Sweet. Elegant.
I've yet to see how Why? uses it. I'll update this post when I get that far. ;-)