开发者

In Sinatra, best way to serve iPhone layout vs. normal layout?

I'm writing a Sinatra app which needs to render different layouts based on whether the user is using an iPhone or a regular browser. I can detec开发者_运维知识库t the browser type using Rack-Mobile-Detect but I'm not sure of the best way to tell Sinatra which layout to use.

Also, I have a feeling that how I choose to do this may also break page caching. Is that true?

Example code:

require 'sinatra/base'
require 'haml'
require 'rack/mobile-detect'

class Orca < Sinatra::Base

  use Rack::MobileDetect

  helpers do
    def choose_layout
      if request.env['X_MOBILE_DEVICE'] == :iPhone
        # use iPhone layout
      else
        # use normal layout
      end
    end
  end

  before do
    # should I use a before filter?
    choose_layout()  
  end

  get '/' do
    haml :home # with proper layout
  end

end #Class Orca


This is what I ended up doing:

require 'sinatra/base'
require 'haml'
require 'rack/mobile-detect'

class Orca < Sinatra::Base

  use Rack::MobileDetect

  # HAML template options
  # Use HTML5 doctype
  set :haml, {:format => :html5 }

  helpers do

    def get_layout
      # For AJAX (XMLHttpRequest) requests, don't use a layout
      if request.xhr? then 
        @layout = false
        exit
      end

      # For non-AJAX (XMLHttpRequest) requests, choose correct layout
      # For each mobile device, you will need a layout_<device>.haml file
      # in the Views directory
      @layout = case request.env['X_MOBILE_DEVICE']
                when /iPhone|iPod/ then :layout_iphone

              # when "Android" then :layout_android

                else true # use default Sinatra layout
                end
    end

  end # helpers

  before do
    get_layout() 
  end # before filter

  get '/' do
    # Will use iPhone layout for iPhone|iPod, 
    # Sinatra default layout for desktop browsers
    haml :home, :layout => @layout
  end

end # Class


I believe the standard way to handle specific user agents in Sinatra is directly on the route...

get '/', :agent => /iPhone/ do
    # render for iPhone
end

get '/' do
    # render standard layout
end

See The Sinatra Book.

Re: caching, I guess it would depend on what caching layers are fronting your site, but, yes, you may need to account for this.


I wrote a blog post about this topic that might be helpful to someone using Padrino with Sinatra. If you're not using Padrino, this still might be useful if you find the right place to extend Sinatra.

http://blog.joshdzielak.com/override-padrino-locale-based-template-resolu
http://dzello.com/blog/2011/06/22/override-padrino-locale-based-template-resolu/

The summary - I use rack-mobile-detect to tell me if a request is 'mobile', and I patch out Padrino's locale-based rendering support to render based on the mobile detection instead of the locale.

In this way I'm able to have foo.mobile.haml render for mobile and foo.haml for non-mobile, without any application code. As a bonus, it works both for the template file and the layout.


I had a similar problem always we cant relay on Routes . Sinatra provides filters to handle these kind of problems

  @your_layout_name = ''

  before :agent => /iPhone/ do
      @your_layout_name = "initialize with desired iphone template"
  end

  get '/' do

    # use @your_layout_name variable to initialize layout 

  end

I posting this since I had a problem where I was not in a position to filter at route level so This may help others who are looking for similar solutions

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜