在Rails中,如何制作:移动视图在找不到后备默认视图?

时间:2012-05-22 17:19:21

标签: ruby-on-rails ruby ruby-on-rails-3

这个问题是对我之前未回答的问题的跟进:ActionView::MissingTemplate: Missing template (Trying to render nonexistent :mobile format )

由于Rails似乎没有与此达成共识,当:html格式不可用时,是否有任何方式从移动设备访问以呈现默认:mobile? (如果存在:mobile视图,则应优先于未进行移动格式化的视图。

3 个答案:

答案 0 :(得分:3)

假设您有一个mobile_request?控制器实例方法来检测移动请求,那么您应该能够设置格式回退链:

# application_controller.rb
before_filter :set_request_format, :set_format_fallbacks

respond_to :html, :mobile # etc

def set_request_format
  request.format = :mobile if mobile_request?
end

def set_format_fallbacks
  if request.format == :mobile
    self.formats = [:mobile, :html]
  end
end

这应该可行,但显然它并不完全。 https://github.com/rails/rails/issues/3855 如果你有一个移动模板,格式似乎被锁定,它将找不到只有html的部分。

希望它会以某种方式修复。 在此期间,您可以将此<%controller.set_format_fallbacks%>在每个模板(ouch)或编写自己的解析器。 http://jkfill.com/2011/03/11/implementing-a-rails-3-view-resolver/

另见:

Can a mobile mime type fall back to "html" in Rails?

Changing view formats in rails 3.1 (delivering mobile html formats, fallback on normal html)

答案 1 :(得分:0)

试试这个:

if File.exists?('app/views/object/mobile.file.erb')
  render :mobile
else
  render :html
end

答案 2 :(得分:0)

我需要同样的事情。我研究了这个包括这个堆栈溢出问题(以及其他类似的问题)以及跟随导线线程(如本问题中提到的)https://github.com/rails/rails/issues/3855并遵循其线程/ gists / gems。

继续我最终做的事情与Rails 3.1和引擎一起工作。此解决方案允许您将* .mobile.haml(或* .mobile.erb等)放在与其他视图文件相同的位置,而不需要2个层次结构(一个用于常规,一个用于移动)。

发动机和准备代码

在我的“基础”引擎中,我在config/initializers/resolvers.rb中添加了此内容:

    module Resolvers
      # this resolver graciously shared by jdelStrother at
      # https://github.com/rails/rails/issues/3855#issuecomment-5028260
      class MobileFallbackResolver < ::ActionView::FileSystemResolver
        def find_templates(name, prefix, partial, details)
          if details[:formats] == [:mobile]
            # Add a fallback for html, for the case where, eg, 'index.html.haml' exists, but not 'index.mobile.haml'
            details = details.dup
            details[:formats] = [:mobile, :html]
          end
          super
        end
      end
    end

    ActiveSupport.on_load(:action_controller) do
      tmp_view_paths = view_paths.dup # avoid endless loop as append_view_path modifies view_paths
      tmp_view_paths.each do |path|
        append_view_path(Resolvers::MobileFallbackResolver.new(path.to_s))
      end
    end

然后,在我的'base'引擎的应用程序控制器中,我添加了一个移动设备?方法:

    def mobile?
        request.user_agent && request.user_agent.downcase =~ /mobile|iphone|webos|android|blackberry|midp|cldc/ && request.user_agent.downcase !~ /ipad/
    end

还有before_filter

    before_filter :set_layout

    def set_layout
      request.format = :mobile if mobile?
    end

最后,我将其添加到config/initializers/mime_types.rb

    Mime::Type.register_alias "text/html", :mobile

用法

现在我可以(在我的应用程序级别或引擎中):

  • app/views/layouts/application.mobile.haml
  • 并且在任何视图中都有.mobile.haml而不是.html.haml文件。

如果我在任何控制器中设置它,我甚至可以使用特定的移动布局:         布局'移动'

将使用app/views/layouts/mobile.html.haml(甚至mobile.mobile.haml)。