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.

Commentary

This is cool. I’m not sure where I’d use it yet, but it’s cool!

Comment by Jeremy Weiskotten on August 21, 2007