ActiveRecord Now Supports an Identity Map. Hooray!

I just read that support for an identity map has just been merged into ActiveRecord. This has been a long time coming and I’m really happy it’s here. Huge thanks to Emilio Tagua for doing this.

In some of my projects an identity map would have saved a lot of ugliness. I’m going to start using this feature in small projects as soon as it’s released. Once it has proven itself to me it will become part of my app template for all my projects. (It’s turned off by default, which seems reasonable for now.)

Read more about it in the link above.

How to Set a Time Zone for Each Request in Rails

The Railscast on Time Zones has some sample code that lets you set a thread-local, per-request time zone with a before_filter:

# controllers/application.rb
  before_filter :set_user_time_zone

  private

  def set_user_time_zone
    Time.zone = current_user.time_zone if logged_in?
  end

Problem is, the current user’s time zone will leak across to the next request on the same thread. If the next one is by a logged-out user, all times displayed on that next request will show in the first user’s time zone.

To prevent this, use an around_filter:

  around_filter :set_time_zone

  private

  def set_time_zone
    old_time_zone = Time.zone
    Time.zone = current_user.time_zone if logged_in?
    yield
  ensure
    Time.zone = old_time_zone
  end

You might be tempted to combine the first two lines of set_time_zone into one line with the comma assignment syntax and add “if logged_in?” to the one line in the ensure clause. Don’t do it. If you did that, the user’s time zone would leak out to the next request when the user logs out.

I’ve submitted a Rails patch to use this method in the sample code for the Time.zone= docs.