Link Search Menu Expand Document

4. 時區設置

4-1 配置台北時區

在 Rails 中,資料庫裡面的時間(datetime)字段一定都是儲存成 UTC 時間。這樣設計的理由是在多國時區的網站中,資料庫比較時間大小需要一致的標準。

編輯 app/views/events/index.html.erb 加上顯示時間:

-  <%= link_to event.name, event_path(event) %>
+ <%= link_to event.name, event_path(event) %> <%= event.created_at %>

image

而 Rails 提供的機制是讓你從資料庫拿資料時,自動幫你轉換時區。例如,請設置 Rails 預設為台北 +8 時區:

修改 config/application.rb

    config.i18n.default_locale = "zh-CN"
+   config.time_zone = "Taipei"

重啟伺服器,就是改成台北時間顯示了。Rails 會幫你自動轉換時區:從資料庫取出來時會加八小時,存回資料庫時會減八小時。

image

4-2 根據用戶配置切換時區

常見的做法是在 Users 上新增一個字段 time_zone:string,儲存該用戶的偏好時區。

執行 rails g migration add_time_zone_to_users

編輯 20170412083439_add_time_zone_to_users.rb

  class AddTimeZoneToUsers < ActiveRecord::Migration[5.0]
    def change
+     add_column :users, :time_zone, :string
    end
  end

執行 rake db:migrate

編輯 config/routes.rb

+  resource :user

注意,這裡的路由設計使用單數 resource :user,跟 resources :users 相比,單數的路由少了 index action,並且網址上不會有 ID,路由方法也皆為單數不需要參數,例如 user_pathedit_user_path。會這樣設計的原因是對前臺用戶而言,編輯用戶資料就是編輯自己的資料,所以這個單數的用意是指唯一自己,用戶也不能修改其他人的資料,因此在 controller 裡面是寫@user = current_user,而不是根據params[:id] 去撈不同用戶。另一個附帶的好處是網址列上不會出現 ID,即使你沒有實作第一章去改 Model 網址,用戶也不會知道 User ID。

執行 rails g controller users

不管單復數 resourceresources 預設的 controller 命名一律是復數型。

編輯 app/controllers/users_controller.rb

class UsersController < ApplicationController

  before_action :authenticate_user!

  def edit
    @user = current_user
  end

  def update
    @user = current_user

    if @user.update(user_params)
      flash[:notice] = "修改成功"
      redirect_to edit_user_path
    else
      render "edit"
    end
  end

  protected

  def user_params
    params.require(:user).permit(:time_zone)
  end

end

編輯 app/views/users/edit.html.erb

<h2>Edit User</h2>

<%= form_for @user do |f| %>

  <div class="form-group">
    <%= f.label :time_zone %>
    <%= f.time_zone_select :time_zone %>
  </div>

  <div class="form-group">
    <%= f.submit "Save", :class => "btn btn-primary" %>
  </div>

<% end %>

編輯 app/views/layouts/application.html.erb


   <ul class="dropdown-menu">
     <li><%= link_to('管理員面板', admin_events_path) %></li>
+    <li><%= link_to('修改個人資料', edit_user_path) %></li>

瀏覽 http://localhost:3000/user/edit 就可以編輯用戶偏好的時區了。

image

不過,真正重點是要在 app/controllers/application_controller.rb 中加入:

+  before_action :set_timezone

+  def set_timezone
+    if current_user && current_user.time_zone
+      Time.zone = current_user.time_zone
+    end
+  end

這樣才會設置 Rails 目前要使用哪個時區。請試著編輯用戶為不同時區,然後觀察看看 http://localhost:3000/events 上面的時間。


Copyright © 2010-2022 Wen-Tien Chang All Rights Reserved.