Filtering by User-Agent in Rails

Back | rails, ruby | 11/3/2011 |

Lets filter out some unwanted browsers from displaying broken pages in our Rails application. We could disallow IE6, for example, but allow IE7, 8 and 9.

Bring in the useragent gem – we’ll need to take it from a popular jillion fork –  it has a ton of fixes that became too hard to merge back to its parent. The latter has many bugs in version comparisons to make it useful for our purposes as of the time of writing this.

  1. gem "useragent", :git => "https://github.com/jilion/useragent.git"

We can add an app_initialization to ApplicationController that all controllers derive from which will render an error page if the browser is not supported.

  1. class ApplicationController < ActionController::Base
  2.   include ApplicationHelper
  3.  
  4.   before_filter :app_initialization
  5.  
  6.   def app_initialization
  7.     if is_browser_unsupported?
  8.       render :template => "errors/browser", :status => 406, :layout => false
  9.     end
  10.   end
  11.  
  12. end

The template can be a page placed in app/views/errors/browser.html.haml.

  1. %html
  2.   %head
  3.     = include_stylesheets :common
  4.     = include_stylesheets :errors
  5.   %body
  6.   
  7.     %h1 Your browser is not supported. We're working on it.
  8.  
  9.     .user_agent
  10.       = @user_agent

Finally, declare an array of supported and an array of unsupported browsers within ApplicationController. A supported browser is a structure of browser name and version. An unsupported browser name is sufficient. We first check whether the browser is explicitly unsupported, then whether the version of a supported browser is bigger or equal to a specific one.

  1. Browser = Struct.new(:browser, :version)
  2. SUPPORTED_BROWSERS = [
  3.   Browser.new("Chrome", "10.0"),
  4.   Browser.new("Safari", "3.0"),
  5.   Browser.new("Firefox", "3.6"),
  6.   Browser.new("Internet Explorer", "9.0"),
  7. ]
  8.  
  9. UNSUPPORTED_BROWSERS = [
  10.   "Opera", "Opera Mini"
  11. ]

Finally, we let everyone with an unknown browser through – we can’t possibly whitelist hundreds of search engine user-agents.

  1. def is_browser_unsupported?
  2.   return false if (Rails.env.test? and request.user_agent.blank?)
  3.   @user_agent = UserAgent.parse(request.user_agent)
  4.   return true if UNSUPPORTED_BROWSERS.include?(@user_agent.browser)
  5.   return true if SUPPORTED_BROWSERS.any? { |browser| @user_agent < browser }
  6.   false
  7. end