First, let's create a homes controller that will enable us to play around with Action Pack Variants, run the commands below to create the home controller now.
rails g controller Homes show
Now let's apply a few simple routes to our application to finish setting things up. Open up your routes file and modify it to look like the code listed below.
Rails.application.routes.draw do resource :home, only: [:show] root to: "homes#show" end
Great! Now we are ready to play around with Action Pack Variants. Action Pack Variants works by using a
before_action in your application controller. Let's create a functional example. Open up your Application Controller and modify so that it looks like the code listed below.
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_browser private def detect_browser 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 else request.variant = :desktop end end end
How does it work? Before an action is called, The
detect_browser is called and the request.variant is set to whatever you want it to be. In the above example we use it determine whether we are running a mobile, tablet, or desktop device. You can actually use it for anything, like detecting Internet Explorer versions (we finally have an easy way to send compatible versions of our site to IE6/7 users!), Looking for special browsers, etc. P.S. that
before_action is the exact same thing as
One more thing to note, this has been stated a bazillion times on other sites, but it's worth repeating here. It's not possible to detect every Android tablet out there. Google currently recommends that Android phone manufacturers have the word 'mobile' in their user agent strings, but there are times where this is not the case. You may have to do some digging around to create some manufacturer specific exception code. However, for the majority of use cases, the above code should detect things fairly well. I've also heard that Microsoft doesn't differentiate tablets running it's mobile operating system. At this early stage in the game it's best just to send all users with Windows Phone in their user agent the phone variant of your site.
Great! Now that we know that, where do we go next? Let's start with something simple. Create a view called
show.html+phone.erb for your homes controller and add in the code listed below.
<h1>Phone</h1> <p> You are running on a smart phone. </p>
Great! Now let's create a view for our tablet users. Create a new view called
show.html+tablet.erb and add in the code listed below.
<h1>Tablet</h1> <p> You are running on a tablet. Whoohoo! </p>
Now, let's modify our default
show.html.erb view. Open it up now and modify it so that it looks like the following code.
<h1>Desktop</h1> <p> All other users get redirected here. </p>
Great! That's set up now, but how do we test? Thankfully Google Chrome includes a very easy way to test. Depending on what platform you are running, this feature might be hidden. First, start your rails server, navigate to your local Rails App, and open up the Chrome Developer tools. You will see something similar to the screenshot listed below. The bar on the bottom can actually be expanded by clicking /dragging up on the gray border. After doing this, clicking the 'Emulation' tab will allow you to select a device to test with. The testing here is very basic, but should be enough to suite our needs.
Let's test our site now, Select 'Google Nexus 4' (a phone) from the Dropdown, then click emulate. Once we do this, our browser will be detected as a phone and the phone template will display in the middle of our browser. Selecting other devices such as 'Apple iPad 1 / 2 / iPad Mini' will render the tablet view.
That's great, but there are still a few pieces of the puzzle left. What if we need to detect the device type prior to rendering the view? For example, setting paging size/options for our queries. Fortunately, this is relatively easy. Open up your homes controller and modify it so that it looks like the code listed below.
class HomesController < ApplicationController def show @device = "others" respond_to do |format| format.html.phone do # phone variant # add code here for phones end format.html.tablet do # tablet variant # add code here for tablets end format.html.desktop do # add code here for desktops and other devices end end # end respond_to end # end show end # end class
Adding code in the format.html blocks listed above allows you to quickly/easily create special queries that are tailored to your device needs. For example, you can make page sizes smaller for mobile devices or send IE6/7 users to a warning page telling them to upgrade their browsers.
Great! However, there is one more thing to cover. What happens if you need to detect the variant in your view? Fortunately this is very easy and be shown with a simple example. Open up your application layout and modify it so that it looks like the code listed below.
Note the if statement starting with
if request.variant.include? :tablet. Why do we use .include? The request.variant is actually an array. Therefore it is necessary to use
That's it! That's all there is to it! Thanks for reading!