Blog Posts

How to create simple mobile version of an existing rails application.

How to create simple mobile version of an existing rails application.

Lets imagine, we have an existing project that we are developing for some time already - 1 year. At the begginig, the client did not want to have mobile version of his website so our all styles and views were developed to work correctly only on desktop and noone bothered about mobile version. Suddenly, after 1 year client wants his site to work properly on mobile devices.

What options do we have?

  • refactor all views and stylesheets to work properly on both desktop and mobile version
  • create new mobile module that will handle mobile devices

The main goals we had to achieve:

  • keep mobile version as simple as possible - advanced stuff only on desktop version
  • all links from desktop version should work on mobile version
  • mobile version should have mobile subdomain
  • index all pages of mobile version in sitemap

To refactor all views to work properly on mobile version, would take quite alot of time. So we decided to create a mobile module that would handle all requests that are comming from mobile versions.

TODO list:

  • duplicate controller from frontend with some changes to keep mobile version as simple as possible
  • create mobile constrain in routes.rb to redirect all requests with mobile subdomain to controller from mobile module
  • create method that will be fired before each action to check whether or not, the request is commign from mobile device
  • redirect desktop urls to mobile, for example: www.sampleweb.com to www.mobile.sampleweb.com

About controllers what we did is absolutely not DRY, but in our case we would need to add additional logic to our controller and we love skinny controller, not fat ones !

Controllers

First duplicate controllers, and adjust them to return only informations that you will need in mobile version. In our case, we cut down some of the advanced searching mechanisms.

Routes

Next lets take care of routes, our main goal is to check whether or not the subdomain consists the mobile pharse. We check it using regexp, /mobile/. If so, we will use controllers from mobile module.

constraints(subdomain: /mobile/) do
    namespace 'mobile', path: '' do
        root 'home#show'
        resources :articles, only: [:index, :show], param: :slug
    end
end
scope 'frontend' do
    root 'home#show'
    resources :articles, only: [:index, :show], params: :slug
end

Redirects

Another important thing, in our TODO list is to create method that will redirect to mobile version from desktop urls and analogicly.

module CheckMobile
  class << self
    def included(klass)
      klass.send :define_singleton_method, :check_mobile do
        before_filter :check_if_user_in_on_mobile_device, only: [:show, :index]
        define_method(:check_if_user_in_on_mobile_device) do
          if browser.device.mobile?
            return if request.subdomain == 'mobile' || request.subdomain == 'www.mobile'
            redirect_to subdomain: 'mobile'
          else
            return if request.subdomain == '' || request.subdomain == 'www'
            redirect_to subdomain: ''
          end
        end
      end
    end
  end
  ActionController::Base.send(:include, CheckMobile)
end

First things first, we are creating singleton method inside ActionController::Base class. The method will be fired before each show/index action to check if request.agent is mobile device. To make things simpler, we are using gem "browser" to check request.agent. If browser.device.mobile? is true, we will change requests subdomain if there is a need to mobile. And analogicly if browser.device.mobile? is false. Of course we have to launch that method in controller, just like any other callback. For example:

class FrontendController < ApplicationController
  check_mobile
end
class MobileController < ApplicationController
  check_mobile
end

So wtih those few simple steps we were able to create backend for mobile version of our application.