【Rails 应用实战】4. 时区设置

308 阅读2分钟

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_pathedit_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 上面的时间。