我正在构建一个通过iFrame与Ruby On Rails一起工作的Facebook应用程序。
我的应用程序确实为多个客户端,网络,移动和Facebook提供服务。根据客户端的类型,UI呈现不同类型的视图。
当用户使用Facebook页面选项卡连接到我的应用程序时,我确实获得了足够的信息(在params集合中)来识别来自facebook的用户。基于此,我可以自定义视图以适应iFrame。
但对于后续请求,因为它们是通过iframe发生的,所以没有任何东西可以告诉这是一个facebook请求(据我所知,除非标题中有一些我不知道的内容)。
我尝试在第一次请求期间设置一个cookie,效果很好。但问题是当用户直接从另一个浏览器标签(而不是通过脸书)请求我的应用时,cookie仍然存在,并且用户最终看到了facebook(ised)UI,而不是普通用户界面。
任何人都有解决方案吗?
答案 0 :(得分:1)
我建议为Facebook标签使用不同的路线。因此,如果您的常规网址如下所示:
/foobar
然后你可能想通过在你的Facebook应用程序选项卡或画布URL中添加“/ fb”前缀(或类似名称)来为Facebook使用这样的东西:
/fb/foobar
在您的routes.rb中,您可以传递参数以指示用户正在Facebook上查看该页面,例如“channel = facebook”或“facebook = true”。
您的routes.rb可能如下所示:
scope 'fb', :channel => 'facebook' do
# ... your routes ...
end
scope :channel => 'web' do
# ... your routes ...
end
通过这些路线,来自Facebook的每个请求将自动具有“channel = facebook”参数。当然,您仍然有责任确保在您的应用中生成相应的网址。您可以将:as => 'facebook'
和:as => web
添加到上述范围,并使用此功能使用专用帮助程序生成网址(例如facebook_foobar_url
,web_foobar_url
)。但最好的方法取决于应用程序的复杂性。
或者,如果您检测到当前请求来自Facebook(来自存在signed_request或你添加的频道/ Facebook参数)。请注意,在Rails 3中不推荐使用此方法,我不太确定Rails 3.1或3.2中的官方替换是什么(如果有的话)。
答案 1 :(得分:0)
我需要以最少的入侵现有代码来解决这个问题。 我在这里发布我的解决方案是为了任何想要解决类似问题的人的利益。
我有一个独特的Facebook布局,这是在第一次请求期间调用的(就像我上面提到的,从facebook标签发布的初始请求有facebook params)。 为了确保后续请求有facebook参数,在facebook布局中,我将所有表单提交和锚点击事件绑定到一个方法,该方法将分别添加隐藏的表单元素和查询字符串参数。
这就是客户端代码的样子:
<script type="text/javascript">
$(document).ready(function() {
$('form').submit(function(e) {
$('<input>').attr({
type: 'hidden',
id: 'fb_param',
name: 'fb_param',
value: 'true'
}).appendTo($(this));
return true;
});
$('a').click(function(e) {
var newUrl = $(this).attr("href");
if (newUrl.indexOf("?") != -1) {
newUrl = newUrl + '&fb_param=true';
} else {
newUrl = newUrl + '?fb_param=true';
}
$(this).attr("href", newUrl);
return true;
});
});
</script>
现在要处理服务器端重定向(通常在更新资源时等),需要扩展redirect_to方法,如下所示:
/app/conntrollers/application_controller.rb
class ApplicationController < ActionController::Base
def redirect_to(options = {}, response_status = {})
if params[:fb_param] == 'true'
if options
if options.is_a?(Hash)
options["fb_param"] = "true"
else
if options.include? "?"
options = "#{options}&fb_param=true"
else
options = "#{options}?fb_param=true"
end
end
end
end
super
end
end