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 detect the browser type using Rack-Mobile-Detect but I'm not sure of the best way to tell Sinatra which layout to use.
我正在编写一个Sinatra应用程序,需要根据用户使用的是iPhone还是常规浏览器来呈现不同的布局。我可以使用Rack-Mobile-Detect检测浏览器类型,但我不确定告诉Sinatra使用哪种布局的最佳方式。
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
4 个解决方案
#1
7
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
#2
4
I believe the standard way to handle specific user agents in Sinatra is directly on the route...
我相信在Sinatra处理特定用户代理的标准方法是直接在路线上......
get '/', :agent => /iPhone/ do
# render for iPhone
end
get '/' do
# render standard layout
end
See The Sinatra Book.
参见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.
Re:缓存,我想这将取决于您的网站面向哪些缓存层,但是,是的,您可能需要考虑到这一点。
#3
1
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.
我写了一篇关于这个主题的博客文章,可能对使用Padrino和Sinatra的人有所帮助。如果您没有使用Padrino,如果找到合适的地方扩展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.
摘要 - 我使用rack-mobile-detect来告诉我请求是否是“移动”,并且我修补了Padrino基于语言环境的渲染支持,以基于移动检测而不是语言环境进行渲染。
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.
通过这种方式,我可以为移动设备提供foo.mobile.haml渲染,为非移动设备提供foo.haml,无需任何应用程序代码。作为奖励,它适用于模板文件和布局。
#4
0
I had a similar problem always we cant relay on Routes . Sinatra provides filters to handle these kind of problems
我有一个类似的问题总是我们不能继续路由。 Sinatra提供过滤器来处理这些问题
@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
我发布这个,因为我遇到了一个问题,我无法在路由级别进行过滤,因此这可能有助于其他正在寻找类似解决方案的人
#1
7
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
#2
4
I believe the standard way to handle specific user agents in Sinatra is directly on the route...
我相信在Sinatra处理特定用户代理的标准方法是直接在路线上......
get '/', :agent => /iPhone/ do
# render for iPhone
end
get '/' do
# render standard layout
end
See The Sinatra Book.
参见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.
Re:缓存,我想这将取决于您的网站面向哪些缓存层,但是,是的,您可能需要考虑到这一点。
#3
1
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.
我写了一篇关于这个主题的博客文章,可能对使用Padrino和Sinatra的人有所帮助。如果您没有使用Padrino,如果找到合适的地方扩展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.
摘要 - 我使用rack-mobile-detect来告诉我请求是否是“移动”,并且我修补了Padrino基于语言环境的渲染支持,以基于移动检测而不是语言环境进行渲染。
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.
通过这种方式,我可以为移动设备提供foo.mobile.haml渲染,为非移动设备提供foo.haml,无需任何应用程序代码。作为奖励,它适用于模板文件和布局。
#4
0
I had a similar problem always we cant relay on Routes . Sinatra provides filters to handle these kind of problems
我有一个类似的问题总是我们不能继续路由。 Sinatra提供过滤器来处理这些问题
@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
我发布这个,因为我遇到了一个问题,我无法在路由级别进行过滤,因此这可能有助于其他正在寻找类似解决方案的人