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

后端 未结 15 1354
余生分开走
余生分开走 2020-12-23 22:17

I\'m using this code (taken from here) in ApplicationController to detect iPhone, iPod Touch and iPad requests:

before_filter :detect_mobile_request, :detec         


        
15条回答
  •  北荒
    北荒 (楼主)
    2020-12-23 22:28

    I need the same thing. I researched this including this stack overflow question (and the other similar one) as well as followed the rails thread (as mentioned in this question) at https://github.com/rails/rails/issues/3855 and followed its threads/gists/gems.

    Heres what I ended up doing that works with Rails 3.1 and engines. This solution allows you to place the *.mobile.haml (or *.mobile.erb etc.) in the same location as your other view files with no need for 2 hierarchies (one for regular and one for mobile).

    Engine and preparation Code

    in my 'base' engine I added this in 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
    

    Then, in my 'base' engine's application controller I added a mobile? method:

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

    And also this before_filter:

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

    Finally, I added this to the config/initializers/mime_types.rb:

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

    Usage

    Now I can have (at my application level, or in an engine):

    • app/views/layouts/application.mobile.haml
    • and in any view a .mobile.haml instead of a .html.haml file.

    I can even use a specific mobile layout if I set it in any controller: layout 'mobile'

    which will use app/views/layouts/mobile.html.haml (or even mobile.mobile.haml).

提交回复
热议问题