Thursday, March 19, 2009

Ruby class method extensions

I have developed a liking to Ruby since I first started using it for automation and now I even started to use it at work for one conversion process. Unfortunately, there are some set backs I've found with Ruby, such as using the Time class. I think my disliking of using it is probably because I've been spoiled with the well developed C# one. It lacks a lot of useful things. However, since Ruby is dynamic, I could make some of the necessary changes myself.

I had to do some extensive operations with the Time class and even though it had a lot of features, it lacked the ones I used the most. It got so bad that at a point, I had to start using Ruby's method extension feature which helped to solve my problem to a great extent.

I would however, like to ask the Ruby developers to clean up their Time class (I am not the only one saying that, just do a google on Ruby's Time class and see what I mean).

To insert class methods is easy. Let me show you:

class Time
class << self
def some_method()
end
end
end

So now I can do this: Time.some_method()

This allows me to insert custom Time creation methods where I can specify a time zone offset along with the time data I want.

What about some instance methods? How can I add for instance a date() method where I can tell Time.now to just give me the date component? Adding a class method won't help here. This requires a little hack (in my opinion).

First the Module:

module TimeInstance
# Converts the time to UTC and converts it
# into epoch in milliseconds
def to_epoch_millis()
(to_f() * 1000.0).to_i()
end

# Gets only the Date component of the current
# time instance
def date()
Time.local(year, month, day, 0, 0, 0, 0)
end
end


And in the Time class:

class Time
...
class << include TimeInstance
end
end


Now I can say: Time.now.date()

Now whatever you add in the TimeInstance module, will be added to the Time class's instance method list. The only catch is, you can only call public methods from the Time class in your module.

But this solves my problem greatly.

Hope this has helped you.

1 comment:

shevy said...

Isnt this code easier?

class Time
def self.some_method()
end
end

I always found class << self very strange idiom in ruby.