config/initializers/mime_types.rb
Mime::Type.register_alias "text/html", :mobile
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_filter :prepare_mobile
private
def prepare_mobile
request.format = :mobile if request_from_mobile_device?
end
def request_from_mobile_device?
env["HTTP_USER_AGENT"].present? && env["HTTP_USER_AGENT"].match(/android/).present?
end
end
app/controllers/foos_controller.rb
class FoosController < ApplicationController
def foo
respond_to do |format|
format.html # foos/foo.html.haml
format.mobile # foos/foo.mobile.haml
format.json { render json: {'success': true} }
end
end
end
Since the format is set to :mobile
, when rendering partials the engine will only look for files with suffix mobile.haml
. This is solvable by patching ActionView like below, but I don't like that.
class ActionView::LookupContext
module DetailsWithHTMLFormat
def formats=(values)
values << :html if values && values.exclude?(:html)
super(values)
end
end
include DetailsWithHTMLFormat
end
With the above code, a mobile device will always get html, even if they request json for example. This can be partially solved by changing should_set_format_to_mobile?
like below.
def prepare_mobile
request.format = :mobile if request_from_mobile_device? && request.format == :html
end
This says that if a mobile device comes in asking for html, give them mobile html. But what if text/html
is not the first entry of the Accept
header? What if a request comes in requesting */*
?
config/initializers/lookup_context.rb
LookupContext.register_detail(:from_mobile_device)
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_filter :prepare_mobile
prepend_view_path MobileViewsResolver.new(Rails.root.join('app/views'))
private
def prepare_mobile
lookup_context.from_mobile_device = true if request_from_mobile_device?
end
def request_from_mobile_device?
env["HTTP_USER_AGENT"].present? && env["HTTP_USER_AGENT"].match(/android/).present?
end
end
app/controllers/foos_controller.rb
class FoosController < ActionController::Base
def foo
respond_to do |format|
format.html # foos/foo.mobile.haml if mobile device, else foos/foo.html.haml
format.json { render json: {'success': true} }
end
end
end
lib/mobile_views_resolver.rb
class MobileViewsResolver < ActionView::FileSystemResolver
def find_templates(name, prefix, partial, details)
return [] unless details[:from_mobile_device]
# lookup files with ".mobile"
end
end