Backbone.js sync()找不到url属性

时间:2013-01-24 01:04:26

标签: backbone.js

使用这个人为的示例代码:

var Product = Backbone.Model.extend({
  idAttribute: '_id',
  url: '/rest/product',
});

var Cart = Backbone.Collection.extend({
  model: Product,
  url: '/rest/cart',
});

p1 = new Product({name: 'Keyboard'});
p2 = new Product({name: 'Mouse'});

c = new Cart();
c.add([p1, p2]);
c.sync();

我看到Error: A "url" property or function must be specified有很多帖子围绕着同样的错误消息,但我找到的所有帖子都是,恰当地,没有在路上某处定义的url属性或函数的结果。

我觉得好像错过了某个链接步骤 - 也许我隐含地依赖于Backbone.js实际上并没有自动设置的“魔术”连接/回调/属性/属性?

5 个答案:

答案 0 :(得分:7)

我认为你不应该直接致电sync;我认为您要找的是c.fetch()(或p1.save(); p2.sav2(),具体取决于您尝试发送数据的方向。同步正是Backbone在内部使用fetch / save所做的事情(如果您想更改如何它们的AJAX详细信息,那么您需要进行同步覆盖,但否则你不应该需要它。)

如果您想方便地保存集合中的每个模型,您可以使用Underscore内置到集合方法“调用”(您应该可以c.save()执行此操作,但我想您可以“T):

 c.invoke('save');

答案 1 :(得分:3)

我首先退后一步,检查您的用例和您选择的架构。您显然正在尝试将产品添加到用户的购物车中。

我看到的问题是你已经把购物车变成了一个集合。我建议把购物车当作包含一系列产品的模型。

var ProductCollection = Backbone.Collection.extend({
    model : Product
});

var Cart = Backbone.Model.extend({
    url : '/rest/cart',
    defaults : {
        products : new ProductCollection()
    }
});

使用这个新架构,你可以这样做:

var c = new Cart();
c.get('products').add([p1, p2]);
c.save();

此架构的另一个好处是,您可以在购物车中添加其他数据属性,例如客户ID,购物车创建时等等。

答案 2 :(得分:1)

对于sync()Backbone.sync方法仅为a proxy

fetch()save()sync()的便捷方法,可让您假设第一个sync()参数('read','patch','update',是一个给定的。

要自己调用此方法,您需要匹配此方法的方法签名才能直接调用它:

Backbone.sync = function(method, model, options)

以下是fetch()的处理方式(注意传递的'read'参数,以及对模型的this引用:

this.sync('read', this, options);

以下是save()的作用:

 method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update');
 if (method === 'patch') options.attrs = attrs;
 xhr = this.sync(method, this, options);

答案 3 :(得分:0)

在这种情况下使用save()而不是sync()

save()基本上通过代理执行Backbone.sync()的工作,但应自动从save的调用者处获取属性。

即使作为模型/集合中的方法调用sync(),您也需要提供您希望同步的模型()作为第二个参数。

所以,myModel.sync('PUT',myModel)会奏效。在具体情况下,c.sync('PUT',c)

答案 4 :(得分:0)

你无法以这种方式保存收藏品;它不是RESTful,因为REST完全是关于转移(单个)模型的状态。因此,Backbone.Collection不支持save()

是有道理的

一种解决方案是在集合上调用.invoke('save'),正如@machineghost建议的那样,但注意这将导致对集合中每个模型的离散请求!如果您要保存多个模型,这可能不是一个好主意。

但是你可以随时保存一个Backbone.Model ......那么为什么不制作一个呢?

var Wrapper = Backbone.Model.extend({
   url: 'api/endpoint'
});
var wrapper = new CollectionWrapperModel({
    cart: c.models
}); 
wrapper.save();

或者,更简洁:

var wrapper = new (Backbone.Model.extend({url: 'api/endpoint'}))({cart: c});
wrapper.save();

请注意,服务器将收到一条POST或PUT消息,其中包含一个名为cart的属性,这是一个包含多个模型的数组,需要进行适当的处​​理。

我意识到提问者为他的问题找到了不同的解决方案,但希望这会对某人有所帮助。