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,储存该用户的偏好时区。
执行bin/rails generate migration add_time_zone_to_users
编辑<timestamp>_add_time_zone_to_users.rb
class AddTimeZoneToUsers < ActiveRecord::Migration[5.0]
def change
+ add_column :users, :time_zone, :string
end
end
执行bin/rails 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。
执行bin/rails generate 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 上面的时间。