3

I'm trying to leverage Rails Variants to use a different layout for phones, and a different one (default one) for tablets+desktops.

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception

  before_action :detect_device_format

  private

    def detect_device_format
      case request.user_agent
      when /iPad/i
        request.variant = :tablet
      when /iPhone/i
        request.variant = :phone
      when /Android/i && /mobile/i
        request.variant = :phone
      when /Android/i
        request.variant = :tablet
      when /Windows Phone/i
        request.variant = :phone
      end
    end
end

class HomeController < ApplicationController
  def index
    respond_to do |format|
      format.json
      format.html          # /app/views/home/index.html.erb
      format.html.phone    # /app/views/home/index.html+phone.erb
      format.html.tablet   # /app/views/home/index.html+tablet.erb
    end
  end
end

Now, I know I can use something like format.html.phone { render layout: 'application-mobile' } but I don't want to do this every single time.

I'd like to keep things dry and create a default phone layout.

How can I accomplish this using Rails 4.1?

sergserg
  • 21,716
  • 41
  • 129
  • 182

2 Answers2

3

This is generic, you can adjust it as you may like.

Application controller:

def set_layout
    case request.user_agent
    when /iPad/i, /Android/i
        "tablet"
    when /iPhone/i, /Android/i && /mobile/i, /Windows Phone/i
        "phone"
    else
        "application"
    end
end

In any controller:

layout :set_layout

EDIT: With this solution you don't have to use this:

format.html          # /app/views/home/index.html.erb
format.html.phone    # /app/views/home/index.html+phone.erb
format.html.tablet   # /app/views/home/index.html+tablet.erb

Everything will respond to

format.html
Ruby Racer
  • 5,690
  • 1
  • 26
  • 43
  • This isn't really what I'm looking for. This will return a string that I'll have to use on each format type. – sergserg May 03 '14 at 21:44
  • Strange, because that's exactly how I'm using it and it's working... "tablet" translates internally into "layouts/tablet.html.erb", "phone" into "layouts/phone.html.erb" etcetera. You don't even have to provide different format types!!! – Ruby Racer May 03 '14 at 21:47
1

Just name your layout {layout}.html+{variant}.erb. For example, if your variant is set to phone, then Rails will look for application.html+phone.erb.

Quico Moya
  • 491
  • 4
  • 5