En Rails, ¿cómo hacer: vistas móviles para retroceder vistas predeterminadas cuando no se encuentran?

Esta pregunta es una continuación de mi anterior pregunta sin respuesta: ActionView::MissingTemplate: plantilla faltante (intentando renderizar inexistente: formato móvil)

Dado que no parece haber un consenso de enfoque de Rails con esto, ¿hay alguna forma de que, al acceder desde un dispositivo móvil, se represente el valor predeterminado? :html cuando :mobile ¿El formato no está disponible? (Si un :mobile vista está presente debe tener prioridad sobre aquellos que no están formateados para dispositivos móviles).

preguntado el 22 de mayo de 12 a las 18:05

3 Respuestas

asume que tienes un mobile_request? método de instancia del controlador para detectar solicitudes móviles, entonces debería poder establecer cadenas de respaldo de formato:

# 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

Esto debería funcionar, pero aparentemente no lo hace completamente. https://github.com/rails/rails/issues/3855 Si tiene una plantilla móvil, el formato parece bloquearse y no encontrará un parcial con solo html.

Esperemos que se solucione de una forma u otra. Mientras tanto, puede poner este <% controller.set_format_fallbacks%> en cada plantilla (ay) o escribir su propio resolver. http://jkfill.com/2011/03/11/implementing-a-rails-3-view-resolver/

también mira:

¿Puede un tipo de mimo móvil recurrir a "html" en Rails?

Cambio de formatos de vista en rails 3.1 (entrega de formatos html móviles, respaldo en html normal)

contestado el 23 de mayo de 17 a las 12:05

Prueba esto:

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

contestado el 22 de mayo de 12 a las 18:05

¿Habría alguna forma de averiguar la plantilla del controlador/acción en lugar de saber exactamente el nombre del archivo? - Travis

Si. params[:action] le da el nombre de la acción. El controlador debe ser constante para el archivo. La ruta sería "app/views/controller/#{params[:action]}.extension". El controlador y la extensión obviamente deberían cambiarse por el nombre del controlador y la extensión de archivo que está utilizando. - sgrif

Bueno, hay una ruta de búsqueda en Rails, solo me preguntaba si había una manera de preguntarle a Rails qué vista "rendería". Supongo que siempre puedes hacer eso. - Travis

Necesito lo mismo. Investigué esto, incluida esta pregunta de desbordamiento de pila (y la otra similar) y seguí el hilo de los rieles (como se menciona en esta pregunta) en https://github.com/rails/rails/issues/3855 y siguió sus hilos / esencias / gemas.

Esto es lo que terminé haciendo que funciona con Rails 3.1 y motores. Esta solución le permite colocar * .mobile.haml (o * .mobile.erb, etc.) en la misma ubicación que sus otros archivos de vista sin necesidad de 2 jerarquías (una para regular y otra para móvil).

Código de motor y preparación

en mi motor 'base' agregué esto en 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

Entonces, ¿en el controlador de aplicaciones de mi motor 'base' agregué un móvil? método:

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

Y tambien esto before_filter:

    before_filter :set_layout

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

Finalmente, agregué esto al config/initializers/mime_types.rb:

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

Uso

Ahora puedo tener (en mi nivel de aplicación o en un motor):

  • app/views/layouts/application.mobile.haml
  • y en cualquier vista un .mobile.haml en lugar de un .html.haml archivo.

Incluso puedo usar un diseño móvil específico si lo configuro en cualquier controlador: diseño 'móvil'

que usará app/views/layouts/mobile.html.haml (o incluso mobile.mobile.haml).

respondido 31 mar '13, 18:03

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.