I'm using this code (taken from here) in ApplicationController to detect iPhone, iPod Touch and iPad requests:
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
This allows me to have templates like show.html.erb, show.mobile.erb, and show.tablet.erb, which is great, but there's a problem: It seems I must define every template for each mime type. For example, requesting the "show" action from an iPhone without defining show.mobile.erb will throw an error even if show.html.erb is defined. If a mobile or tablet template is missing, I'd like to simply fall back on the html one. It doesn't seem too far fetched since "mobile" is defined as an alias to "text/html" in mime_types.rb.
So, a few questions:
If it matters, I'm using Rails 3.0.1. Thanks in advance for any pointers.
EDIT: Something I forgot to mention: I'll eventually be moving to separate sub-domains (as you can see commented out in my example) so the template loading really needs to happen automatically regardless of which before_filter
has run.
MIME types are traditionally written in all lowercase, but MIME types are actually case in-sensitive. HTML elements such as the <a> , <embed> , <link> , <object> and <style> tags will use a MIME type in the type attribute.
MIME (Multipurpose Internet Mail Extension) media types were originally devised so that e-mails could include information other than plain text. MIME media types indicate the following things − How different parts of a message, such as text and attachments, are combined into the message.
MIME types are officially supposed to be assigned and listed by the Internet Assigned Numbers Authority (IANA). Many of the popular MIME types in this list (all those begin with "x-") are not assigned by the IANA and do not have official status.
A MIME type (or media type) is an identifier for file formats or format contents on the Internet. MIME stands for Multipurpose Internet Mail Extensions and all MIME types are officially maintained by the Internet Assigned Numbers Authority (IANA).
Possible Duplicate of Changing view formats in rails 3.1 (delivering mobile html formats, fallback on normal html)
However, I struggled with this exact same problem and came up with a fairly elegant solution that met my needs perfectly. Here is my answer from the other post.
I think I've found the best way to do this. I was attempting the same thing that you were, but then I remembered that in rails 3.1 introduced template inheritance, which is exactly what we need for something like this to work. I really can't take much credit for this implementation as its all laid out there in that railscasts link by Ryan Bates.
So this is basically how it goes.
Create a subdirectory in app/views
. I labeled mine mobile
.
Nest all view templates you want to override in the same structure format that they would be in the views directory. views/posts/index.html.erb -> views/mobile/posts/index.html.erb
Create a before_filter
in your Application_Controller
and do something to this effect.
before_filter :prep_mobile
def is_mobile?
request.user_agent =~ /Mobile|webOS|iPhone/
end
def prep_mobile
prepend_view_path "app/views/mobile" if is_mobile?
end
Once thats done, your files will default to the mobile views if they are on a mobile device and fallback to the regular templates if a mobile one is not present.
You need to do several things to wire this up, but the good news is that Rails 3 actually makes this a lot simpler than it used to be, and you can let the router do most of the hard work for you.
First off, you need to make a special route that sets up the correct mime type for you:
# In routes.rb:
resources :things, :user_agent => /iPhone/, :format => :iphone
resources :things
Now you have things accessed by an iphone user agent being marked with the iphone mime type. Rails will explode at you for a missing mime type though, so head over to config/initializers/mime_types.rb and uncomment the iphone one:
Mime::Type.register_alias "text/html", :iphone
Now you're mime type is ready for use, but your controller probably doesn't yet know about your new mime type, and as such you'll see 406 responses. To solve this, just add a mime-type allowance at the top of the controller, using repsond_to:
class ThingsController < ApplicationController
respond_to :html, :xml, :iphone
Now you can just use respond_to blocks or respond_with as normal.
There currently is no API to easily perform the automatic fallback other than the monkeypatch or non-mime template approaches already discussed. You might be able to wire up an override more cleanly using a specialized responder class.
Other recommended reading includes:
https://github.com/plataformatec/responders
http://www.railsdispatch.com/posts/rails-3-makes-life-better
Trying removing the .html from the .html.erb and both iPhone and browser will fallback to the common file.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With