Continuing with my exploration of Ruby on Rails as a .NET guy, here’s an awesome example of Convention over Configuration at work. I decided to add bite size snippets of some of the cool things I encountered in Ruby and Rails. If you are interested in others, see my other Ruby posts.

Time zone handling has always been one of those things that I’ve tried to avoid. A recent ASP.NET app I was working on needed to support time zones and it was quite a pain to implement. Well, within the context of Rails, I was astonished at how easy it was to handle time zones.

By default, ActiveRecord stores datetimes in the database as UTC (although you can change this behavior, however, I’m not sure where this would actually be helpful). This makes it very easy to convert a datetime to another time zone.

Conversion Magic

At the application level, you can set a default time zone. Within your environment.rb file (sort of like an ASP.NET web.config file), you can just simply set:

config.time_zone = "Eastern Time (US & Canada)"

Now, when you display a date within a view it will be converted to EST –5:00 (or EDT –4:00 like it is now). Also, when a user enters a date, it will be entered as Eastern Time, and it will be converted and saved to the DB as UTC.

More Conversion Sweetness

So an application level setting is great if all your users are in your time zone, but that’s rarely the case. Luckily changing a time zone for a user is a snap as well.

There are many ways to store the time zone information for a user, which I won’t get into here, but it could simply be an attribute on your User model, which is what I’ll assume you are doing for this example. I’ll also assume that you have a current_user method that returns the current logged in user. From there, the code to set a time zone is just four lines.

The first step is to add a method to your ApplicationController. This method will be what actually changes the time zone. Using a current_user method to access the current user, we can do:

def set_time_zone
  Time.zone = current_user.time_zone if current_user
end

The last step is to wire up this call in a before_filter, which will fire before a request (since all your controllers inherit from the application_controller).

before_filter :set_time_zone

That is seriously all that is involved. That is a real thing of beauty.

Further Research

There are a few sites that I would recommend you check out in learning about time zones in Rails. This time zones handling came along with Rails 2.1 so these links are all dedicated to the 2.1 release, but time zones work fine in Rails 2.3.5.