After about eight hours of trial and error I have come up with a solution that works for now. Perhaps this may be of interest to someone with a similar setup.
I started by adding a column to the users table and corresponding attribute in the model – session_tz_offset
.
Then I started hacking around with Warden callbacks. What worked for me was to put a helper method in the ApplicationController, and call that with a before filter like this:
before_filter :authenticate_user!, :set_session_tz_offset_for_user
helper_method :set_user_time_zone, :set_session_tz_offset_for_user
def set_session_tz_offset_for_user
Warden::Manager.after_authentication do |user, auth, opts|
if (params[:user])
user.session_tz_offset = params[:user][:session_tz_offset]
user.save
end
end
end
The after_authentication callback fires several times during login, why is unknown to me. Not all of these calls have a params[:user] field, and if I didn't check for it, my application crashed with a undefined method [] for nil:NilClass
error.
When the session_tz_offset
is set, my other controllers use another helper method, also defined in ApplicationController to set Time.zone
for the current request:
def set_user_time_zone
if (user_signed_in?)
if(user_session[:time_zone])
Time.zone = user_session[:time_zone]
else
user_session[:time_zone] =
ActiveSupport::TimeZone.[](current_user.session_tz_offset)
Time.zone = user_session[:time_zone]
end
else
Time.zone = config.time_zone
end
end