豆知识

Turbolinks

Turbolinks 是一个 Javascript 套件,作用是使得网站在换页的时候,不重新载入 HTML 的 head ,只载入新的 body ,以此达到加速换页的目的。

但是 Turbolinks 有两个坑。

第一个坑

如果在页面中用了其他的 JavaScript 代码,并且用了类似 $(document).ready(function(){...}) 这样的语句,意思是等待 HTML 载入完成后执行 js 的代码。这时的 turbolinks 就会使得这些 js 代码只会执行一次,也就是换页,再换回来的时候,这些 js 代码失效了。原因就是 turbolink 为了换页加速,不重新载入 HTML 的 head 代码。

解法是,改成 $(document).on("trbolinks:load", function(){...})

第二个坑

如果是写在 body 里的 js 代码,换页之后再换回来时,因为 turbolink 的机制,会使得这些 js 代码执行两次。

解法一:关掉 Turbolinks 的缓存功能,把 <meta name="turbolinks-cache-control" content="no-cache"> 放到 layout 的 head 里面。

解法二:把layout 的<body> 改成<body id="<%= "#{controller_name}-#{action_name}"%>">,这样就可以在全局载入的application.js 中指定只有这一页才执行的js code,例如:

终极解法

有一个终极解法,就是把 Turbolinks 拆掉。

第一步:修改 Gemfile,把 gem 'turbolinks' 删除;

第二步:在 application.js 里把 //= require turbolinks 删除;

第三步: 在 application.html.erb 里,把 <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> 改成 <%= javascript_include_tag 'application' %>

to_param重写

调用路由方法的时候, Rails 默认用 to_param 方法来转换 ID,例如

event_path(@event) 等同于 event_path(@event.to_param)

to_param 是默认的方法,默认是这样定义的

def	to_param
  self.id
end

我们可以重定义,比如说在 event.rb 这个 model 里

def	to_param
  "#{self.id}-#{self.name}"
end

这样再次调用 event_path(@event) 时,出来的网址就会是 /events/xxx-name 的样子。

在 controller 里用了 @event = Event.find(params[:id]) ,其中在调用 find 方法之前会先用 to_iparam[:id] 转换成纯数字,其中的非数字字符都会被忽略掉了。所以 controller 的原代码依然可用。

国际化

config/locales/application.rb 设置默认语言

  class Application < Rails::Application
  +  config.i18n.default_locale = "zh-CN"
  end

国际化的相关 gem

gem "rails-i18n"
gem "devise-i18n"

config/locales 下增加设定档。

设定时区

config/locales/application.rb 设置

class Application < Rails::Application
  +  config.time_zone = "Beijing"
end

还可以让用户在个人信息中选择自己的时区,然后在 application_controller.rb 加一个 set_timezone 的方法。

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_action :set_timezone
  def set_timezone
    if current_user && current_user.time_zone
      Time.zone = current_user.time_zone
    end
  end
end

格式化时间

Ruby 内建了 strftime 这个方法来格式化输出,例如

<%= event.created_at.strftime("%Y/%m/%d %I:%M %p") %>

这样就会输出成例如 2017/04/10 05:53 PM 了。

除此之外,还可以用 to_s 来格式化时间,例如

datetime = Time.now

datetime.to_s(:db)            # => "2007-12-04 00:00:00"
datetime.to_s(:number)        # => "20071204000000"
datetime.to_s(:short)         # => "04 Dec 00:00"
datetime.to_s(:long)          # => "December 04, 2007 00:00"
datetime.to_s(:long_ordinal)  # => "December 4th, 2007 00:00"
datetime.to_s(:rfc822)        # => "Tue, 04 Dec 2007 00:00:00 +0000"
datetime.to_s(:iso8601)       # => "2007-12-04T00:00:00+00:00"

to_s 的格式也可以自己定义,方法是在 config/application.rb 最后新增一行

Time::DATE_FORMATS.merge!(:default => '%Y/%m/%d %I:%M %p', :ymd => '%Y/%m/%d')

这样就会 1. 修改默认的时间显示格式 2. 注册一个新的格式是 ymd 只有日期。

<%= event.created_at.to_s %> 会输出 2017/04/10 05:53 PM

如果只想显示日期,可以改成 <%= event.created_at.to_s(:ymd) %>

· rails