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

后端 未结 15 1194
余生分开走
余生分开走 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:19

    Trying removing the .html from the .html.erb and both iPhone and browser will fallback to the common file.

    0 讨论(0)
  • 2020-12-23 22:20

    If your OS has symlinks you could use those.

    $ ln -s show.html.erb show.mobile.erb
    
    0 讨论(0)
  • 2020-12-23 22:21

    Rails 4.1 includes Variants, this is a great feature that allow you to set different views for the same mime. You can now simply add a before_action and let the variant to do the magic:

    before_action :detect_device_variant
    
    def detect_device_variant
      case request.user_agent
      when /iPad/i
        request.variant = :tablet
      when /iPhone/i
        request.variant = :phone
      end
    end
    

    Then, in your action:

    respond_to do |format|
      format.json
      format.html               # /app/views/the_controller/the_action.html.erb
      format.html.phone         # /app/views/the_controller/the_action.html+phone.erb
      format.html.tablet do
        @some_tablet_specific_variable = "foo"
      end
    end
    

    More info here.

    0 讨论(0)
  • 2020-12-23 22:23

    I solved this problem by using this before_filter in my ApplicationController:

    def set_mobile_format
      request.formats.unshift(Mime::MOBILE) if mobile_client?
    end
    

    This puts the mobile format to the front of the list of acceptable formats. So, the Resolver prefers .mobile.erb templates, but will fall back to .html.erb if no mobile version is found.

    Of course, for this to work you need to implement some kind of #mobile_client? function and put Mime::Type.register_alias "text/html", :mobile into your config/initializers/mime_types.rb

    0 讨论(0)
  • 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).

    0 讨论(0)
  • 2020-12-23 22:30

    You need to do several things to wire this up, but the good news is that Rails 3 actually makes this a lot simpler than it used to be, and you can let the router do most of the hard work for you.

    First off, you need to make a special route that sets up the correct mime type for you:

    # In routes.rb:
    resources :things, :user_agent => /iPhone/, :format => :iphone
    resources :things
    

    Now you have things accessed by an iphone user agent being marked with the iphone mime type. Rails will explode at you for a missing mime type though, so head over to config/initializers/mime_types.rb and uncomment the iphone one:

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

    Now you're mime type is ready for use, but your controller probably doesn't yet know about your new mime type, and as such you'll see 406 responses. To solve this, just add a mime-type allowance at the top of the controller, using repsond_to:

    class ThingsController < ApplicationController
      respond_to :html, :xml, :iphone
    

    Now you can just use respond_to blocks or respond_with as normal.

    There currently is no API to easily perform the automatic fallback other than the monkeypatch or non-mime template approaches already discussed. You might be able to wire up an override more cleanly using a specialized responder class.

    Other recommended reading includes:

    https://github.com/plataformatec/responders

    http://www.railsdispatch.com/posts/rails-3-makes-life-better

    0 讨论(0)
提交回复
热议问题