0

In my Rails app, I want to show all time instances in the timezone set by the user's preference rather than UTC.

This a common problem, and I have seen solutions to change the default UTC to one specific timezone (like EDT). I want to make the times dynamic though, and I would like to do it in my time_formats.rb initializer on the server side. In other words, users should be able to see a time in GMT 0, GMT +1, or GMT +2 based on their preference.

I have done this in a way that works locally but breaks when pushed to Heroku. Here's what I set up.

First, I have added timezone as a column in my Devise user model.

class AddTimezoneToUsers < ActiveRecord::Migration
  def change
     add_column :users, :timezone, :string
  end
 end  

Next, I am formatting my time-formats.rb with:

 Time::DATE_FORMATS[:default] = in_time_zone("%I:%M %p")

Locally, this works great. I can change my time zone preference in Settings and it adjusts across all time instances. However, my push to Heroku has failed for the following reason:

 .../bundle/ruby/2.2.0/gems/activesupport-4.0.4/lib/active_support/values/time_zone.rb:283: 
 warning: circular argument reference - now
 remote:        rake aborted!
 remote:        NoMethodError: undefined method `in_time_zone' for main:Object

Having found in_time_zone from the Rails class documentation, why is it working locally but causing a method issue in Heroku?

EDIT 1: Just had another thought, and I wanted to add some other debugging. Since it is a method error, I now checked my ApplicationController.

 before_filter :set_timezone

 def set_timezone
    tz = current_user ? current_user.timezone : nil
    Time.zone = tz || ActiveSupport::TimeZone["London"]
  end

Since that is setting the default as London before a user changes current_user.timezone, I don't think it should conflict. Wanted to include though.

Community
  • 1
  • 1
darkginger
  • 652
  • 1
  • 10
  • 38

2 Answers2

1

After debugging for another hour, I figured out my mistake.

In the time_formats.rb file where I am trying to set the time zone to the user's preference, I used the following:

Time::DATE_FORMATS[:default] = in_time_zone("%I:%M %p")

The in_time_zone was causing the problem. I am already setting using the Application Controller to modify the time to the user's setting with current_user.timezone : nil. By changing my time_formats.rb to:

 Time::DATE_FORMATS[:default] = "%I:%M %p"

I am now showing the correct time based on the user settings, and I can push to Heroku successfully while letting the Application Controller do the work.

darkginger
  • 652
  • 1
  • 10
  • 38
0

Setting timezone as per user in server might not be a good idea, what happens if the user moves to a different timezone, are you going to change all the time instances saved in server to that?

What I have found from googling it that, do not interfere with specific timezone's in server, but create a timezone attribute for user and serve contents accordingly.

I found out that the below blog post describes about this scenario very well. https://www.reinteractive.net/posts/168-dealing-with-timezones-effectively-in-rails

Gokulnath
  • 321
  • 3
  • 6
  • I may be misunderstanding. In my strategy above, the user is setting their own timezone attribute in the User model (by the selection they are making in registration or if they go back and edit it). The `time_formats.rb` then modifies the time across the site (which works locally). Is that not serving the contents based on the timezone attribute? – darkginger Feb 14 '16 at 04:46