What is RubySpec?

You might think that What is the meaning of life? is a tough question. But here’s one that will give it a run for its money: What is Ruby?

Ok sure, that comparison is hyperbole, but bear with me. Try this out in your irb session:

>> Float("0.5") == "0.5".to_f
=> true

That’s reasonable enough. Imagine if it weren’t true! But did you know that the Float() method converted the "0.5" text string to a Float object without calling the string’s to_f() method?

What is the definition of Ruby in this situation? Is it that Float() returns a Float object for a validly formatted text string or that Float() does so without calling the string’s to_f() method? Let’s investigate the situation a bit more.

In Ruby, if you define an arbitrary object that you want to behave like a Float object, you define a to_f() method for your object. Then Float() will call that method on your object:

>> s = "0.5"
=> "0.5"
>> def s.to_f() 42 end
=> nil
>> floaty = Object.new
=> #<Object:0x5eb190>
>> def floaty.to_f() 0.5 end
=> nil
>> Float(floaty) == Float(s)
=> true

Now that is surprising. A lot of the elegance of Ruby comes from generally everything being an object. In some sense, floaty and "0.5" are just objects, so why does the Float() method treat them differently?

More importantly, should you rely on Float() not calling your string’s to_f() method, or is that merely an implementation detail of MRI (Matz’s Ruby Implementation)? This is the dilemma faced repeatedly by every alternative Ruby implementation.

Fortunately, we have a powerful tool to assist us.

The RubySpec project is writing an executable definition of the Ruby programming language using RSpec-style specs. The tremendous utility of the specs is that alternate Ruby implementations can run them to determine if they are building a compatible Ruby engine.

Presently, the specs contain over 33,000 precisely defined facets of Ruby behavior. The specs cover Ruby behavior across different platforms, operating systems, and versions of the Ruby language. The goal is to ensure that Ruby applications written to use the core Ruby features covered by the specs will run the same on any Ruby implementation.

RubySpec has been well-known in the community of Ruby implementers for almost two years. Every major Ruby implementation is using it. However, many Ruby programmers are just learning about it. RubySpec has a lot to contribute to the larger Ruby community. Recently, I explain some ideas about this in an interview with Gregory Brown. Greg is starting a project, called Unity, to make the information contained in the RubySpecs more accessible to everyone.

Contributing to RubySpec is a great way to learn more about the Ruby programming language. At the same time, your contribution helps the alternate Ruby implementations and the Ruby ecosystem. In the past couple of weeks, contributors have added tons of fixes to the specs for Ruby 1.8.7 and 1.9. Check out their excellent work at the RubySpec Github repository.

I’ll be speaking about RubySpec at the upcoming Open Source Bridge conference June 17-19. If you have questions about RubySpec that you’d like me to address, please leave a comment.