Rails Rails Variants Tips

lanvige · 2014年09月11日 · 最后由 realwol 回复于 2014年10月16日 · 7018 次阅读
本帖已被管理员设置为精华贴

原贴 http://lanvige.github.io/2014/09/11/rails-variants-tips/

现在 Web 界流行一个新词Responsive Web Design,目的就是让一套网页在不同的设备上都能展现内容,像 BootStrap 这样的主流框架也都对其进行支持,很是方便,但有时不同设备上要求是不同的,可以说是完全不同的样式,在开发过程中仍需要使用不同的模板来渲染。

Image source:

提到不同模板,在 Rails 中,普遍的方案是加入一个新的 Mime,为这种 Mime 建一个 Template Engine。 示例:RailsCasts #199 Mobile Devices

Action Pack Variants

Rails 4.1 中推出了一个新功能 Action Pack Variants,主要就是简化多设备上的模板问题。

具体用法

#抄自 release notes

# You can set the variant in a before_action:
request.variant = :tablet if request.user_agent =~ /iPad/

#Respond to variants in the action just like you respond to formats:
respond_to do |format|
  format.html do |html|
    html.tablet # renders app/views/projects/show.html+tablet.erb
    html.phone { extra_setup; render ... }
  end
end

# Provide separate templates for each format and variant:

app/views/projects/show.html.erb
app/views/projects/show.html+tablet.erb
app/views/projects/show.html+phone.erb
You can also simplify the variants definition using the inline syntax:

respond_to do |format|
  format.js         { render "trash" }
  format.html.phone { redirect_to progress_path }
  format.html.none  { render "trash" }
end

Tip 1 判断浏览器类型

判断浏览器是一件很烦的事情,好在有很多地方都已经写好可以借用:如ruby-china

不过这里要推荐的是一个 gem,叫作browser

gem 'browser'

然后就可以享受到多如牛毛的判断,更多看 github 页面。

browser.name 
browser.mobile?
browser.tablet?
browser.firefox?
browser.ie?
browser.ie6?      

Tip 2 参数指定浏览器类型

通过手机,模拟器可以看到效果,但调试起来却不方便,在 Chrome 中安装 Agnet Simulate 是个好办法,但... RailsCast 中给出了一个通过 params 来改变状态的方法,这里依然实用。

def mobile_device?
  session[:mobile_override] = params[:mobile] if params[:mobile]
  if session[:mobile_override]
    session[:mobile_override] == '1'
  else
    browser.mobile?
  end
end

通过 params mobile=1 来强制设定浏览器类型,然后将其存到 session 中,即可以方便的调试。

Tip 3 Devise 等如何使用

上面示例中,把判断设备的代码放在了 application_controller.rb 中,但如果在像 devise 中如何使用 Variants 呢?

因为 devise 的自定义类中,会继承class RegistrationsController < ::Devise::RegistrationsController,而非 application_controller.rb,所以判断方法无法在这里使用。

第一个方案是,在自定义类中重写一变判断方法,Too Sha too kill...

第二种,可以使用Concerns

# controllers/concerns/detect_format_variant.rb
module DetectFormatVariant
  extend ActiveSupport::Concern

  included do
    before_filter :set_device_type
  end

  private

  ## Mobile device
  # detect_device
  # 用Rails 4.1中的variants来进行设备匹配
  def set_device_type
    session[:mobile_override] = params[:mobile] if params[:mobile]
    if mobile_device?
      request.variant = :phone
    end
  end

  def mobile_device?
    if session[:mobile_override]
      session[:mobile_override] == '1'
    else
      browser.mobile?
    end
  end
end

在需要进行判断的 controller 中加入

# Base controller
class ApplicationController < ActionController::Base
  include DetectFormatVariant
end

# Devise
class RegistrationsController < ::Devise::RegistrationsController
  include DetectFormatVariant
end

REF::

如果想深入了解 Variants,可以看看这篇: http://ryanbigg.com/2009/04/how-rails-works-2-mime-types-respond_to/

我发现我就是来蹭首页的,哈哈。每次被踢下去时,就写一篇新文~~~

其实真的没必要,那么多的模板,维护起来极其麻烦。同一个设备还有横有竖,和别的模板又有重复。

只是网站而已,不必当 mobile app 来要求,Responsive 写好了,一点都不费事。

#2 楼 @billy 不同设备输出内容有可能很大不同,不只是样式问题,所以感觉这个还是挺有用的,只是我还没这么用过?

这个功能不够新

#2 楼 @billy 在具备 Responsive 的情况下依然有使用这个特性的场景,比如 App 内嵌页面,需要展现上做一些特殊处理,但数据结构不变。

正被这样的事情困扰呢,pc web,mobile web

移动设备是万恶之源。

还是有用的

tip2,三年前我使用了这个方法,我甚是欣慰。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号