I\'m after some validation that I\'m doing the right thing. I have my Ruby on Rails application in the following structure:
/home
about.rhtml<
The Iphone actually does a pretty good job of rendering web pages without any special formatting.
However on my Android phone floated content seems to get cut off and so a custom view for that phone is required. To achieve this you need to create a different layout (e.g. mobile_application.html.erb) and in your application_controller add the following:
layout :select_layout
def select_layout
session.inspect # force session load
if session.has_key? "layout"
return (session["layout"] == "mobile") ? "mobile_application" : "application"
end
return detect_browser
end
def detect_browser
agent = request.headers["HTTP_USER_AGENT"].downcase
MOBILE_BROWSERS.each do |m|
return "mobile_application" if agent.match(m)
end
return "application"
end
where MOBILE_BROWSERS is a an array of user agent strings you want to match as a mobile device.
I wrote a blog about this here:
http://www.arctickiwi.com/blog/2-mobile-enable-your-ruby-on-rails-site-for-small-screens
Cheers
Rails 4.1 includes Variants, a great new feature that:
Allows you to have different templates and action responses for the same mime type (say, HTML). This is a magic bullet for any Rails app that's serving mobile clients. You can now have individual templates for the desktop, tablet, and phone views while sharing all the same controller logic.
In your case, you only need to set the variant for the iphone in a before_action
, e.g:
class HomeController < ApplicationController
before_action :detect_iphone
def index
respond_to do |format|
format.html # /app/views/home/index.html.erb
format.html.phone # /app/views/home/index.html+phone.erb
end
end
private
def detect_iphone
request.variant = :iphone if request.user_agent =~ /iPhone/
end
end
What's new in Rails 4.1
firstly, you should be using .html.erb as your template extension
secondly you can use logic to detect the type of layout to use based on the user agent (request.user_agent
).
layout :site_layout
def site_layout
some_way_to_detect_the_layout_to_use
end
Note, the user_agent can be faked, but a majority of people wont bother faking it so the solution should be "good enough" for 99.9% of cases.
I would strongly recommend leaving the controller structure the same across all device types. Particularly if you are using Rails' RESTful routes your controllers should be closely matched to the domain model of your data. Whether that data is then presented to a desktop browser, to an iPhone, to a different type of mobile device, to a JSON/XML REST API client etc. is mostly a matter of the presentation layer, not the controller/routing layer.
So an elegant solution would be:
respond_to
mechanism to render a different view format for each device type;There are some plugins which try to make this easier: have a look at brendanlim's Mobile Fu and noelrappin's Rails iUI (both on GitHub). Also Brendan Lim's presentation at Rails Underground has a few ideas.
What you should be aiming for is something like:
def show
@foo = Foo.find(params[:id])
respond_to do |format|
format.html # => show.html.erb
format.iphone # => show.iphone.erb
format.blackberry # => show.blackberry.erb
end
end
You should also allow users on mobile devices to override the user agent detection if they really want to see the desktop version of the site. A cookie with a long expiry time is probably the best way to do this, so that the site remembers the choice next time the user returns. Some mobile devices have rubbish cookie support, but then they probably won't want the desktop version of the site anyway because it probably won't work.