背景
我用“rails g scaffold hotel name stars:integer”快速启动(并在数据库中插入一些记录), 并在rails app之外写一个Backbone客户端。
我使用Safari文件在本地打开Backbone客户端:///Users/lg/Workspace/www/index.html用于测试客户端,因为我的想法是将rails服务器放在主机上(例如Heroku)并插入Backbone客户端进入PhoneGap应用程序。
我的骨干客户端只有几行:
Hotel = Backbone.Model.extend({
initialize: function(){
console.log("initialize Hotel")
}
});
Hotels = Backbone.Collection.extend({
model: Hotel,
url: 'http://0.0.0.0:3000/hotels'
});
但是当我获取带有主干的酒店时,rails会使用 format.html 而不是Backbone可以解析的 format.json 进行响应。
hotels_controller.rb
# GET /hotels
# GET /hotels.json
def index
@hotels = Hotel.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: @hotels }
end
end
Safari检查员控制台:
hotels = new Hotels()
Object
hotels.fetch()
Object
hotels.length
0
Request URL:http://0.0.0.0:3000/hotels
Request method:GET
Status code:200 OK
Request Headers
Accept:application/json, text/javascript, */*; q=0.01
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/534.53.11 (KHTML, like Gecko) Version/5.1.3 Safari/534.53.10
Response Headers
Cache-Control:max-age=0, private, must-revalidate
Connection:Keep-Alive
Content-Length:2233
Content-Type:text/html; charset=utf-8
Date:Sat, 11 Feb 2012 14:31:52 GMT
Etag:"606da2b7c21ca96c9d71aabccdd439e9"
Server:WEBrick/1.3.1 (Ruby/1.9.2/2011-07-09)
修改 更新了url设置为url:“http://0.0.0.0:3000/hotels.json
它可以捕捉,但不能使其他人CRUD(例如PUT)
hotels = new Hotels()
Object
hotels.fetch()
Object
hotels.length
5
hotel = hotels.get(2)
Object
hotel.set({name: "name 2"})
Object
hotel.save()
Object
PUT http://0.0.0.0:3000/hotels.json/2 404 (Not Found)
相反,如果我只设置/酒店工作(但骨干客户端必须驻留在服务器上)
编辑2:
在github上传代码
https://github.com/RevH/backbonefails
编辑3:
另一个细节是,如果您将backboneclient目录插入Rails公共目录并将0.0.0.0:3000/hotels.json更改为/ hotels它的工作非常棒!!但是,如果我将客户端与服务器分开并用Safari打开它,则需要在URL的末尾使用.json。这很奇怪。
的github上打开了一个rails问题答案 0 :(得分:10)
要理解的重要一点是,Rails中的最佳实践不是使用Accept标头。有一个很好的写作here,可以用光荣的细节解释原因。摘要是HTTP Accept标头的浏览器实现已损坏。 Rails的最佳实践是在请求中设置:format参数。但是,如果您喜欢它们受支持的接受标题,但有关rails中有效接受标头的规则可能会非常棘手。如果您的接受标头与以下正则表达式匹配:
BROWSER_LIKE_ACCEPTS = /,\s*\*\/\*|\*\/\*\s*,/
然后rails抛弃它并默认为text / html mime类型。我知道,对吧?您的标题恰好与此匹配。大多数人没有这个问题的原因是rails“修复”了rails jquery-ujs中的默认jquery行为。他们在JQuery中设置了ajaxSetup之前的回调,它将*/*
放在标题的开头,这就是魔术乐队正则表达式想要看到的,虽然我不知道为什么,除了他们知道未经修改的浏览器请求将始终把它放在那里。以下是如何修复JQuery中的接受标头。
$(function() {
$.ajaxSetup({
'beforeSend': function(xhr) {
xhr.setRequestHeader("accept", "application/json");
}
});
});
答案 1 :(得分:1)
您已设置rails代码,因此需要调用/hotels.json
才能返回json,但您的骨干代码仅调用/hotels
。
解决这个问题的最简单方法是为json数据设置一个单独的api,而不是html页面。例如:/hotels
返回html,/api/hotels
返回json。请参阅Ryan Bate的Railscasts,了解这个(付费)http://railscasts.com/episodes/323-backbone-on-rails-part-1
另一种选择是更改Backbone模型/集合,以便将“.json”附加到网址的末尾。例如:
Backbone.Model.extend({
url: function(){
var url;
if (this.isNew()){
url = "/hotels/" + this.id + ".json";
} else {
url = "/hotels.json";
}
return url;
}
});
还有其他选择。这些只是我头脑中的两个。
答案 2 :(得分:0)
当您的javascript应用程序在与服务器不同的域,端口或协议上运行时,会发生奇怪的事情。这称为同源策略。只需从rails服务器加载javascript,一切都会好的。