I have been meaning to do some more blogging about why I like Ruby so much. In fact, I tell my friends that in the short term, I don't think I could enjoy any other language. Why? The first thing that comes to mind is that Ruby is such a language that you can manipulate it to allow you do express logic in English (almost). If you are familiar with Ruby on Rails, then you have see some of these "extensions" that allow you to express logic in a more meaningful and concise way. What does this really mean? It means that I can write code that looks so much like English that anyone, including our spouses or significant others, could at least understand what is trying to be accomplished. This may be a stretch, but let me get on to some examples.
When I deal with dates in many environments, especially databases, there seems to be a different way to manipulate dates and time. Usually there are time and date objects that you have to instantiate and then manipulate in order to get what you want. Let's say that I want to get a time object for a time in the past. Let's say three weeks ago. You should be able to say, give me the date from three weeks ago in one statement. Object instantiation and manipulation is not meaning for to people looking at your code. It should be concise.
Three weeks ago starts with a number. In this case the number is 3, but it could be any number. In ruby, numbers are Fixnum classes (Rails uses Nummeric). If you evaluate the following code in ruby, you can see what the class is:
3.class # => Fixnum
Now, ideally, we would like to call a method on 3 to get some representation of weeks. How does this work?
3.weeks # => # ~> -:1: undefined method `weeks' for 3:Fixnum (NoMethodError)
In Ruby, you are able to open up any object and manipulate it. In this case, we want to add an method named "weeks". The Ruby time class uses seconds in its mathematical operations, so we need to calculate the number of seconds in a week. The following code will show you how to add a method to the Fixnum class.
class Fixnum def weeks self*7*24*60*60 end end 3.weeks # => 1814400 Time.now # => Wed Oct 15 10:14:29 -0500 2008 Time.now - 3.weeks # => Wed Sep 24 10:14:29 -0500 2008
We are getting close. Doing a mathematical operation to determine the time that we want is not very meaningful. We can add a method called "ago" that will do the math for us. This will yield an expression that anyone can understand.
class Fixnum def ago Time.now - self end end 3.weeks # => 1814400 Time.now # => Wed Oct 15 10:14:29 -0500 2008 # Finally: 3.weeks.ago # => Wed Sep 24 10:14:29 -0500 2008
The following is the code that I usually use in my projects that I have to deal with time extensively. You may have a question about the alias commands in the class declaration. Those will allow you do use singular or plural versions of the same function.
# Open up the Fixnum class and some class methods. class Fixnum def second self end alias :seconds :second def minute 60.seconds*self end alias :minutes :minute def hour 60.minutes*self end alias :hours :hour def day 24.hours*self end alias :days :day def week 7.days*self end alias :weeks :week def ago Time.now - self end end Time.now # => Tue Oct 14 22:48:27 -0500 2008 3.hours.ago # => Mon Oct 13 19:48:27 -0500 2008 1.week.ago # => Tue Oct 07 22:48:27 -0500 2008
I am not sure where this originated, but the first time that I came across it was in Rails. If you look in activesupport, there are many, many examples of extensions that help make your code more meaningful. This simple concept as really made programming fun again. Writing concise code that people can actually read is rewarding for me.
blog comments powered by Disqus