NubyGems : What are These() ?

by Gregory Brown

The following may be a bit of an 'Advanced NubyGem' but I think this is an interesting idiom that most people will have to work with.

Sometimes in Ruby you'll see things, both in core and third party libraries, that look a bit like class names that take arguments.

You may of already seen these in the form of Integer(), Array(), etc.

>> Integer(1)
=> 1
>> Integer("1")
=> 1
>> Integer("")
ArgumentError: invalid value for Integer: ""
from (irb):3:in `Integer'
from (irb):3

These weird looking methods are just alternate constructors. They can really come in handy as a way to simplify the most common ways of building a given object, or giving them some different behaviors.

Here is an example from Ruport:

The long way of constructing a Table object:

table = :data => [[1,2,3],[4,5,6]],
:column_names => %w[a b c]

This is the shortcut interface:

table = Table(%w[a b c]) << [1,2,3] << [4,5,6]

This is usually less typing and looks a little cleaner. Of course, it doesn't support the same exact options of the original constructor, but that's what we're going for afterall.

How it's done

Implementing these methods is as simple as using capitalized method names. In Ruport, we are currently a little surly and do this right on Kernel so you can get the constructors everywhere:

module Kernel
def Table(*args)
#implementation here

A safer way

Instead of sticking these methods in Kernel, you can play it safe and put them in a module,
this way, they only are available where you include them. For example, if enough people complain, we'll probably do something like this:

module Ruport::Data::Shortcuts
def Table(*args)

This way, people would be able to use these shortcuts just in certain classes by including the module in them. If you're worried about your names conflicting with others, this might be a good idea.

Don't Overuse Your Shortcuts!

I should fix this problem before I tell folks not to do it, but right now bits of Ruport code use the shortcut methods internally. Unless you have a really compelling reason (other than laziness) to do this, Don't!

The very thing that makes it 'safe enough' to stick these shortcuts in core is that a conflict should only break the shortcut. If you use your shortcuts internally in your code, there is a chance of some serious issues if things collide.


2007-03-22 10:06:35
Adding these to Kernel seems a little dangerous from a security perspective, could you tell us how to prevent people from doing this. Is there a way in ruby to change the security level?
Gregory Brown
2007-03-22 10:10:22
I'm not sure what security issues you're interested in, besides the usual risk of name collision.

Can you let me know a little bit more about your concerns so I can understand the problem better?