Handling User Timezones in Ruby on Rails: A Comprehensive Guide
August 14, 2024
Handling User Timezones in Ruby on Rails: A Comprehensive Guide
In today’s globalized world, displaying times in a way that suits each user’s local timezone is crucial for user experience. This guide will walk you through adding and managing user timezones in a Ruby on Rails application using Devise, and how to display timestamps in a user-friendly format.
Adding Timezone Support to Your Rails Application
1. Add a Timezone Column to the User Model
First, you need to add a timezone
column to the users
table. This allows each user to have a personalized timezone setting.
Generate a migration:
rails generate migration AddTimezoneToUsers timezone:string
rails db:migrate
2. Permit the Timezone Parameter in Devise
To allow Devise to handle the timezone
parameter during sign-up and profile updates, override the RegistrationsController
:
Generate the controller if you haven’t already:
rails generate devise:controllers users
Update app/controllers/users/registrations_controller.rb
:
class Users::RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: [:create]
before_action :configure_account_update_params, only: [:update]
protected
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up, keys: [:timezone])
end
def configure_account_update_params
devise_parameter_sanitizer.permit(:account_update, keys: [:timezone])
end
end
3. Update Your Routes
Ensure your routes use the custom controller:
devise_for :users, controllers: {
registrations: 'users/registrations'
}
4. Add Timezone Selection to Forms
Sign-Up Form
Modify app/views/devise/registrations/new.html.erb
to include a timezone dropdown:
<div class="field">
<%= f.label :timezone %><br />
<%= f.select :timezone, ActiveSupport::TimeZone.all.map { |tz| [tz.name, tz.name] }, {}, class: "form-control" %>
</div>
Edit Profile Form
Similarly, update app/views/devise/registrations/edit.html.erb
:
<div class="field">
<%= f.label :timezone %><br />
<%= f.select :timezone, ActiveSupport::TimeZone.all.map { |tz| [tz.name, tz.name] }, {}, class: "form-control" %>
</div>
5. Apply User’s Timezone Throughout the Application
Add a method to your ApplicationController
to use the user’s timezone:
class ApplicationController < ActionController::Base
around_action :set_time_zone
private
def set_time_zone(&block)
timezone = current_user.try(:timezone) || 'UTC'
Time.use_zone(timezone, &block)
end
end
Displaying Timestamps in a User-Friendly Format
To ensure that timestamps are displayed in a readable format with AM/PM notation:
1. Format the Time with AM/PM
Use strftime
to format the timestamp in your views. For example:
<td><%= click.created_at.in_time_zone(current_user.timezone).strftime("%Y-%m-%d %I:%M:%S %p") %></td>
This will display timestamps in the format:
2024-08-03 02:37:40 AM
2. Example Code
Here’s how you would incorporate this into your view:
<td><%= click.created_at.in_time_zone(current_user.timezone).strftime("%Y-%m-%d %I:%M:%S %p") %></td>
Committing Your Changes
To document these changes in your version control, use a clear and descriptive commit message. For example:
Format timestamps with AM/PM for user-friendly display
- Updated the view to format `created_at` timestamps with AM/PM notation.
- Converted timestamps to the user's timezone before formatting.
- Applied `%I:%M:%S %p` format to display hours in 12-hour clock with AM/PM indicator.
This change improves readability for users by displaying times in a more conventional AM/PM format.
Summary
Handling user timezones in a Rails application involves:
- Adding a
timezone
attribute to theusers
model. - Permitting and handling timezone parameters in Devise.
- Displaying timestamps in a user-friendly format, including AM/PM notation.
By following these steps, you enhance user experience by ensuring that times are displayed according to each user's local timezone and in an easily readable format.