16 Aug

Integer.returns_many lets you return 7.somethings

In my last post I mentioned my love of all things ActiveSupport. I’m particularly fond of how it modifies the core Integer class to easily convert between units of time:

Time.now + 7.days
=> Thu Aug 23 04:05:54 UTC 2007

Time.now – 1.month
=> Tue Jul 17 04:06:12 UTC 2007

Recap: ActiveSupport is a Rails library that modifies core Ruby classes with handy utility methods like the ones above.

Anyways, I love this syntax, and began wondering how it could be re-applied to other objects. My first idea – what about retuning an arbitrary number of objects, of any class? Wouldn’t it be neat to return 7.somethings?

It turns out you can do just that.

I can has apples?

Let’s say we have a class called Apple with a single attribute – a color.

class Apple
  attr_accessor :color

  def initialize(color = nil)
    self.color = color
  end  
end

a_red_apple = Apple.new(‘red’)

Using Integer.returns_many, a little 15-line class method I’ve written, we can make any Integer return a corresponding amount of objects, returned in an array. It has one required argument – the pluralized version of the class you’d like to return.

In keeping with our example, lets have Integers return instances of our Apple class:

Integer.returns_many(‘apples’)
=> true

Applesauce

After invoking the returns_many method, all Integers are blessed with the ‘apples’ method.

3.apples
=> [ #<Apple:0xb7c70e04 @color=[]>, 
     #<Apple:0xb7c70df0 @color=[]>,
     #<Apple:0xb7c70ddc @color=[]> ]

Any arguments you pass to the ‘apples’ method gets passed to the Apple#initialize method (the class constructor). This means we can give our apples color:

2.apples(‘green’)
=> [ #<Apple:0xb7c70e04 @color=["green"]>, 
     #<Apple:0xb7c70ddc @color=["green"]> ]

Since we’re dealing with arrays now, array arithmetic works dandy. If I fill my basket with 2 green apples and 1 red apple, what have I got?

basket = 2.apples(‘green’) + 1.apple(‘red')
=> [ #<Apple:0xb7c70e04 @color=["green"]>, 
     #<Apple:0xb7c70df0 @color=["green"]>,
     #<Apple:0xb7c70ddc @color=["red"]> ]

Conclusion and Source code

Fixnum.many_things might be of limited usefulness, but it’s an interesting example of how Ruby’s core types can be modified to make code reading easier.

If you’d like to give Integer.returns_many a try, you can check out the code here.

Oh, and please forgive my lolcats reference above.