Может ли мобильный mime-тип вернуться к «html» в Rails? - PullRequest
22 голосов
/ 31 октября 2010

Я использую этот код (взятый из здесь ) в ApplicationController для обнаружения запросов iPhone, iPod Touch и iPad:

before_filter :detect_mobile_request, :detect_tablet_request

protected

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

def mobile_request?
  #request.subdomains.first == 'm'
  request.user_agent =~ /iPhone/ || request.user_agent =~ /iPod/
end

def detect_tablet_request
  request.format = :tablet if tablet_request?
end

def tablet_request?
  #request.subdomains.first == 't'
  request.user_agent =~ /iPad/
end

Это позволяет мне иметь такие шаблоны, как show.html.erb, show.mobile.erb и show.tablet.erb, и это здорово, но есть проблема: кажется, я должен определить каждый шаблон для каждого типа пантомимы. Например, запрос действия «show» у iPhone без определения show.mobile.erb вызовет ошибку, даже если определен show.html.erb. Если шаблон для мобильного телефона или планшета отсутствует, я хотел бы просто вернуться к HTML. Кажется, это не слишком далеко, поскольку «mobile» определяется как псевдоним «text / html» в mime_types.rb.

Итак, несколько вопросов:

  1. Я делаю это неправильно? Или есть лучший способ сделать это?
  2. Если нет, могу ли я использовать типы mime для мобильных устройств и планшетов для html, если файл для мобильного телефона или планшета отсутствует?

Если это имеет значение, я использую Rails 3.0.1. Заранее спасибо за любые указатели.

РЕДАКТИРОВАТЬ: Кое-что я забыл упомянуть: в конечном итоге я перейду к отдельным поддоменам (как вы можете видеть закомментировано в моем примере), поэтому загрузка шаблона действительно должна происходить автоматически независимо от того, который before_filter бежал.

Ответы [ 15 ]

1 голос
/ 31 октября 2010

Да, я уверен, что это правильный способ сделать это на рельсах.Я определил форматы iPhone таким образом раньше.Это хороший вопрос о том, чтобы вернуть формат по умолчанию обратно: html, если шаблон для iphone не существует.Это звучит достаточно просто, но я думаю, что вам придется добавить в monkeypath либо спасение пропавшей ошибки шаблона, либо проверить, существует ли шаблон перед рендерингом.Взгляните на тип патчей, показанный в этот вопрос .Что-то вроде этого, вероятно, подойдет (запись этого кода в моем браузере, так что больше псевдокода), но добавьте это в инициализатор

# config/initializers/default_html_view.rb
module ActionView
  class PathSet

    def find_template_with_exception_handling(original_template_path, format = nil, html_fallback = true)
      begin
        find_template_without_exception_handling(original_template_path, format, html_fallback)
      rescue ActionView::MissingTemplate => e
        # Template wasn't found
        template_path = original_template_path.sub(/^\//, '')
        # Check to see if the html version exists
        if template = load_path["#{template_path}.#{I18n.locale}.html"]
          # Return html version
          return template
        else
          # The html format doesn't exist either
          raise e
        end
      end
    end
    alias_method_chain :find_template, :exception_handling

  end
end
0 голосов
/ 31 марта 2013

Мне нужно то же самое. Я исследовал это, включая вопрос переполнения стека (и другой аналогичный вопрос), а также следил за потоком рельсов (как упоминалось в этом вопросе) на https://github.com/rails/rails/issues/3855 и следовал за его потоками / гистами / драгоценными камнями.

Вот то, что я закончил, работает с Rails 3.1 и движками. Это решение позволяет вам размещать * .mobile.haml (или * .mobile.erb и т. Д.) В том же месте, что и другие файлы просмотра, без необходимости в двух иерархиях (одна для обычной и одна для мобильных).

Код двигателя и приготовления

в моем «базовом» движке я добавил это в 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

Тогда в контроллере приложения моего «базового» движка я добавил мобильный? Метод:

    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).

0 голосов
/ 09 марта 2012

Я сделал для этого обезьяний патч , но сейчас я использую лучшее решение:

В application_controller.rb:

layout :which_layout

def which_layout
  mobile? ? 'mobile' : 'application'
end

С mobile? метод, который вы можете написать.

Так что у меня другой макет, но все те же виды, и в макете mobile.html.erb я использую другой файл CSS.

0 голосов
/ 30 января 2012

Я решил эту проблему с помощью этого before_filter в моем ApplicationController:

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

Это помещает мобильный формат в начало списка допустимых форматов. Итак, Resolver предпочитает .mobile.erb шаблоны, но вернется к .html.erb, если мобильная версия не найдена.

Конечно, чтобы это работало, вам нужно реализовать какую-то функцию #mobile_client? и поместить Mime::Type.register_alias "text/html", :mobile в config/initializers/mime_types.rb

.
0 голосов
/ 31 октября 2010

Вы можете в этом случае для формата html.В качестве примера вы всегда хотите использовать html в методе пользовательского показа

class UserController

  def show
    ..your_code..
    render :show, :format => :html
  end
end

. В этом случае, если вы запрашиваете показ на контроллере пользователя, вы все время визуализируете HTML-версию.

Если вы хотитерендеринг JSON тоже, например, вы можете сделать некоторые проверки о вашем типе, как:

class UserController

  def show
    ..your_code..
    if [:mobile, :tablet, :html].include?(request.format)
      render :show, :format => :html
    else
      respond_with(@user)
    end
  end

end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...