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 %>
而 Rails 提供的機制是讓你從資料庫拿資料時,自動幫你轉換時區。例如,請設置 Rails 預設為台北 +8 時區:
修改 config/application.rb
config.i18n.default_locale = "zh-CN"
+ config.time_zone = "Taipei"
重啟伺服器,就是改成台北時間顯示了。Rails 會幫你自動轉換時區:從資料庫取出來時會加八小時,存回資料庫時會減八小時。
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_path
、edit_user_path
。會這樣設計的原因是對前臺用戶而言,編輯用戶資料就是編輯自己的資料,所以這個單數的用意是指唯一自己,用戶也不能修改其他人的資料,因此在 controller 裡面是寫@user = current_user
,而不是根據params[:id]
去撈不同用戶。另一個附帶的好處是網址列上不會出現 ID,即使你沒有實作第一章去改 Model 網址,用戶也不會知道 User ID。
執行 rails g controller users
不管單復數
resource
或resources
預設的 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
就可以編輯用戶偏好的時區了。
不過,真正重點是要在 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 上面的時間。