Converting tzinfo from rails 2.0 to 2.1

Written by on Jun 9 2008

For those of you cool enough to have time zone support in your pre-rails 2.1 app, here is how you can convert the tzinfo stuff to the new way.

  • In you environment.rb, change config.active_record.default_timezone = :utc to config.time_zone = ‘UTC’.
  • In your application.rb change the set_timezone around filter to a before filter. Make sure it is called after there is a valid user.

    • In that filter, you probably have two paths, one for a user and one for no user. Change the user line from TzTime.zone = user.tz to Time.zone = user.tz. Remove the other path, it’s no longer necessary.
  • In your users model you can remove the line that used to say: composed_of :tz, :class_name => ‘TZInfo::Timezone’, :mapping => %w( time_zone time_zone ).

    • Just make sure the column that holds the time_zone info is called “time_zone.”
  • Remember the helper method called “tz” which converts the times in columns to the user’s time? Remove it, this happens automatically now.

  • Delete the tz* plugins.

  • If you had something like this in your view: <%= time_zone_select ‘person’, :time_zone, TZInfo::Timezone.us_zones, :model => TZInfo::Timezone > change it to <= time_zone_select ‘person’, :time_zone, TimeZone.us_zones %>.

  • Trevor has created a nice little script that will migrate your existing users’ time zone data to the new format. (The string that holds the time zone data has changed in the new version, so we have to map the old strings to the new.)

    • You will want to use the PseudoCursors plugin or the WIll Paginate pagination stuff instead of User.find.all.each so you don’t kill your server when running this migration.
    • Thanks Trevor!

One unresolved problem: If you used something like the previous helper method to display the drop down of time choices you find that what is returned in the new list is significantly shorter, and they all have different values. E.G. in the old list you would find things like: “America/New_York,” “Africa/Ndjamena,” and “Etc/GMT-7” but in the new list the items are like this: “Eastern Time (US & Canada),” “Nairobi,” and “Wellington.” The problem is that we need to convert the values in our production apps to the new values. I haven’t figured out a way to do this yet. If you open script/console in a < 2.1 app you can find the old values are generated via: TZInfo::Timezone.get(TZInfo::Timezone.all_identifiers0), which returns the first time zone. The to_s and name methods are what get called on the object to create the value and text for the options. In a 2.1 app, TimeZone.all7 is what get called to find the 8th time zone. (to_s and name are still what get called.) I haven’t yet figured out how to map the old to the new, assuming there is a way. If someone figures this out, please post in the comments and I’ll update this post.

One last bit of coolness.

The new method of doing time zones even works when rendering values from the model. So on those rare times when you need to render HTML from the model (like if you’re sending HTML via XMPP) you don’t have to jump through any hoops to make that happen.

Meet
Steven

Hi I'm Steven,

I wrote the article you're reading... I lead the developers, write music, used to race motorcycles, and help clients find the right features to build on their product.

Get Blog Updates