Saturday 13 September 2008

xUnit in Ruby

I'm working my way through Kent Beck's excellent "Test Driven Development: By Example". Part 2 is all about using TDD to write an xUnit framwork. The examples are in Python. I decided to replicate them in Ruby for the practice:


And the rest...

Sunday 8 June 2008

Ruby Idiom #1 and beyond: class <<self; self end

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. ;-)

Further Reading:

Sunday 13 April 2008

Likin' RDoc

I've moved onto part 2 of Pickaxe. Currently on the RDoc chapter. I must say I'm impressed how smiple it seems to keep things. No fancy @param annotations to learn, just put a comment above your class / attribute / method and you're off. If you feel the need for more control of your formatting, you can get busy with a very wiki-like syntax.

Its also interesting to note that if you click on a method, RDoc will show you the code. It highlights a key difference between the Java and Ruby worlds.

Sunday 6 April 2008

Unit Testing in Ruby

Ruby comes with a Unit Test framework pre installed: Nathaniel Talbott's Test::Unit. The Pickaxe book devotes a whole chapter to it (and not at the back). These are good things.

Saturday 5 April 2008

Ruby I/O - Calling File.open with a block does the .close for me

More Ruby niceness. This should look familiar to all Java guys and gals out there:


Repeat after me: "Always be closing. Always be closing. Always be closing."

But Ruby's File.open can also take a block to associate with the call:


This invokes the block, passes the newly opened file to it as a parameter. When this is complete, the file is automatically closed for you.

In addition to this, if an exception ocurs in the first example then the close will never be called until its GC'd. (Bet you'd miss checked exceptions then). With the second example, the file is closed and then the exception is propogated to the caller.

Monday 31 March 2008

Lost a Safety Net

I've just finished working through Chapter 9 of Pickaxe - Modules - and to be honest, it sacred me a little. Now I'm not religiously tied to static languages and can see the benefits something dynamic like Ruby can bring to me but there was something about Modules and name spaces which had me yearning for good 'ole Duke.

Here's the scoop. Mixins (using Modules as a way to provide multiple inheritance) allow you to provide instance variables. If I create an @myString instance variable in my mixin, and then in my class which includes it I also have an instance variable with the same name it can all go horribly wrong.

But here's the pain. In nice statically checked land, the compiler (best chum o' mine) will flag my goof. In Ruby-land, there is no compiler. Things might even work for a while. Worse still they miht break without my knowing it. Then finding the problem would be pretty nasty and debug-steppy.

Now I know I should have created a nice set of unit tests to avoid this, but in a complex application I can see things like this falling between the cracks; horrible nasty cracks with spikes and stuff at the bottom. Yurgh!

Or am I just being over sensitive?

Before I close, there are a few other confusions this deceptively short chapter threw up:
  1. I thought everything in Ruby was a class. Even objects. How come then Pickaxe states "a module isn't a class" (page 119). Hmmm.
  2. include / require / load / aaaaarhg! I like Java's "import" better and despite the problems, classpaths sheild the rest from me in 90% of situations (though heaven forbid when I have to debug a classloader problem, or worst still, implement one of my own...)

Saturday 5 January 2008

Ruby Has No "for" Loop - Woo Hoo!

I held onto my hat when I heard this one. I use the 'for' loop in Java a lot. Probably more than I ought. 'How will this work' I thought? No 'for' loop? Nonsense ...


When I saw it I liked it. Its often said (by me too earlier) that one of the reasons Ruby is so great is that it reads. Well, here's another example of just that. I like.

Glorious Negated "if" - "unless"

It continues! More and more comfort and joy ... Behold:


Ahhhh! A warm hug from my code.

Ruby If Expressions- Terse and Legible

More Ruby Pickaxe Learning. "if" expressions today (not "if" statements either - they return values don't you know). I was pleased to see just how terse and legible they can be:


Beautiful.