保存整个系列的最佳做法?

时间:2021-06-02 21:47:07

Say that I have a Collection and I've made changes to many of its Models. What's the best way to save all of the changes using a single HTTP request?

假设我有一个Collection,并且我对其许多模型进行了更改。使用单个HTTP请求保存所有更改的最佳方法是什么?

4 个解决方案

#1


24  

Usually REST backends handle single instance creation/update. You would need to change that to accept an array of objects.

通常,REST后端处理单个实例创建/更新。您需要更改它以接受对象数组。

That said, on the client side, you would need to go directly to the Backbone.sync function

也就是说,在客户端,您需要直接进入Backbone.sync功能

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

In this case your model should be an array of model. The method should be "create" or "save" and the options take the same type of options as a jQuery ajax call (error, success, etc.)

在这种情况下,您的模型应该是一个模型数组。该方法应该是“创建”或“保存”,并且选项采用与jQuery ajax调用相同类型的选项(错误,成功等)

#2


12  

I'm going to do the Wrong Thing here and quote Wikipedia regarding proper RESTful practices: a PUT to example.com/resources should replace the entire collection with another collection. Based on this, when we had to support editing multiple items simultaneously, we wrote up this contract.

我将在这里做错误的事情并引用*关于正确的REST实践:对于example.com/resources的PUT应该用另一个集合替换整个集合。基于此,当我们不得不支持同时编辑多个项目时,我们写了这份合同。

  1. The client sends {"resources": [{resource1},{resource2}]}
  2. 客户端发送{“资源”:[{resource1},{resource2}]}
  3. The server replaces the entire collection with the new information from the client, and returns the information after it's been persisted: {"resources": [{"id":1,...},{"id":2,...}]}
  4. 服务器用来自客户端的新信息替换整个集合,并在持久化后返回信息:{“resources”:[{“id”:1,...},{“id”:2,.. }]}

We wrote the server half of the contract in Rails, but here's the client half (in CoffeeScript, sorry!):

我们在Rails中写了服务器的一半合同,但这是客户端的一半(在CoffeeScript中,抱歉!):

class ChildElementCollection extends Backbone.Collection
  initialize: ->
    @bind 'add', (model) -> model.set('parent_id', @parent.id)

  url: -> "#{@parent.url()}/resources" # let's say that @parent.url() == '/parent/1'
  save: ->
    response = Backbone.sync('update', @, url: @url(), contentType: 'application/json', data: JSON.stringify(children: @toJSON()))
    response.done (models) => @reset models.resources

I thought this was a lot easier to implement then overriding Backbone.sync. One comment on the code, our collections were always child objects, which should explain why the code sets a "parent_id" whenever an object is added to the collection, and how the root of the URL is the parent's URL. If you have root-level collections that you want to modify, then just remove the @parent business.

我认为这更容易实现,然后重写Backbone.sync。关于代码的一个注释,我们的集合总是子对象,这可以解释为什么代码在将对象添加到集合时设置“parent_id”,以及URL的根如何是父对象的URL。如果您要修改根级别集合,则只需删除@parent业务。

#3


6  

You should extend Backbone.Collection, giving it a save() method that would check each of its models hasChanged().

你应该扩展Backbone.Collection,给它一个save()方法来检查它的每个模型hasChanged()。

Then it should call Backbone.sync, which you'll probably have to extend a little into a custom sync function. If you do use a custom Backbone.sync function, then be sure to set it on your collection.

然后它应该调用Backbone.sync,您可能需要将其扩展到自定义同步功能。如果您使用自定义Backbone.sync函数,请务必在集合中设置它。

var CollectionSync = function(method, model, [options]) {
    // do similar things to Backbone.sync
}

var MyCollection = Backbone.Collection.extend({
    sync: CollectionSync,
    model: MyModel,
    getChanged: function() {
        // return a list of models that have changed by checking hasChanged()
    },
    save: function(attributes, options) {
        // do similar things as Model.save
    }
});

A different approach (using a model to represent the collection) is here: "How" to save an entire collection in Backbone.js - Backbone.sync or jQuery.ajax?

一种不同的方法(使用模型来表示集合)在这里:“如何”在Backbone.js中保存整个集合 - Backbone.sync或jQuery.ajax?

I also like https://*.com/a/7986982/137067

我也喜欢https://*.com/a/7986982/137067

#4


0  

This code adds a new method to the collection prototype just to call the save method of those models that had changed. It worked for me:

此代码为集合原型添加了一个新方法,只是为了调用那些已更改的模型的save方法。它对我有用:

Backbone.Collection.prototype.saveAll = function(options) {
 return $.when.apply($, _.map(this.models, function(m) {
   return m.hasChanged() ? m.save(null, options).then(_.identity) : m;
 }));
};

Gist link: https://gist.github.com/julianitor/701c677279bac1529b88

要点链接:https://gist.github.com/julianitor/701c677279bac1529b88

#1


24  

Usually REST backends handle single instance creation/update. You would need to change that to accept an array of objects.

通常,REST后端处理单个实例创建/更新。您需要更改它以接受对象数组。

That said, on the client side, you would need to go directly to the Backbone.sync function

也就是说,在客户端,您需要直接进入Backbone.sync功能

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

In this case your model should be an array of model. The method should be "create" or "save" and the options take the same type of options as a jQuery ajax call (error, success, etc.)

在这种情况下,您的模型应该是一个模型数组。该方法应该是“创建”或“保存”,并且选项采用与jQuery ajax调用相同类型的选项(错误,成功等)

#2


12  

I'm going to do the Wrong Thing here and quote Wikipedia regarding proper RESTful practices: a PUT to example.com/resources should replace the entire collection with another collection. Based on this, when we had to support editing multiple items simultaneously, we wrote up this contract.

我将在这里做错误的事情并引用*关于正确的REST实践:对于example.com/resources的PUT应该用另一个集合替换整个集合。基于此,当我们不得不支持同时编辑多个项目时,我们写了这份合同。

  1. The client sends {"resources": [{resource1},{resource2}]}
  2. 客户端发送{“资源”:[{resource1},{resource2}]}
  3. The server replaces the entire collection with the new information from the client, and returns the information after it's been persisted: {"resources": [{"id":1,...},{"id":2,...}]}
  4. 服务器用来自客户端的新信息替换整个集合,并在持久化后返回信息:{“resources”:[{“id”:1,...},{“id”:2,.. }]}

We wrote the server half of the contract in Rails, but here's the client half (in CoffeeScript, sorry!):

我们在Rails中写了服务器的一半合同,但这是客户端的一半(在CoffeeScript中,抱歉!):

class ChildElementCollection extends Backbone.Collection
  initialize: ->
    @bind 'add', (model) -> model.set('parent_id', @parent.id)

  url: -> "#{@parent.url()}/resources" # let's say that @parent.url() == '/parent/1'
  save: ->
    response = Backbone.sync('update', @, url: @url(), contentType: 'application/json', data: JSON.stringify(children: @toJSON()))
    response.done (models) => @reset models.resources

I thought this was a lot easier to implement then overriding Backbone.sync. One comment on the code, our collections were always child objects, which should explain why the code sets a "parent_id" whenever an object is added to the collection, and how the root of the URL is the parent's URL. If you have root-level collections that you want to modify, then just remove the @parent business.

我认为这更容易实现,然后重写Backbone.sync。关于代码的一个注释,我们的集合总是子对象,这可以解释为什么代码在将对象添加到集合时设置“parent_id”,以及URL的根如何是父对象的URL。如果您要修改根级别集合,则只需删除@parent业务。

#3


6  

You should extend Backbone.Collection, giving it a save() method that would check each of its models hasChanged().

你应该扩展Backbone.Collection,给它一个save()方法来检查它的每个模型hasChanged()。

Then it should call Backbone.sync, which you'll probably have to extend a little into a custom sync function. If you do use a custom Backbone.sync function, then be sure to set it on your collection.

然后它应该调用Backbone.sync,您可能需要将其扩展到自定义同步功能。如果您使用自定义Backbone.sync函数,请务必在集合中设置它。

var CollectionSync = function(method, model, [options]) {
    // do similar things to Backbone.sync
}

var MyCollection = Backbone.Collection.extend({
    sync: CollectionSync,
    model: MyModel,
    getChanged: function() {
        // return a list of models that have changed by checking hasChanged()
    },
    save: function(attributes, options) {
        // do similar things as Model.save
    }
});

A different approach (using a model to represent the collection) is here: "How" to save an entire collection in Backbone.js - Backbone.sync or jQuery.ajax?

一种不同的方法(使用模型来表示集合)在这里:“如何”在Backbone.js中保存整个集合 - Backbone.sync或jQuery.ajax?

I also like https://*.com/a/7986982/137067

我也喜欢https://*.com/a/7986982/137067

#4


0  

This code adds a new method to the collection prototype just to call the save method of those models that had changed. It worked for me:

此代码为集合原型添加了一个新方法,只是为了调用那些已更改的模型的save方法。它对我有用:

Backbone.Collection.prototype.saveAll = function(options) {
 return $.when.apply($, _.map(this.models, function(m) {
   return m.hasChanged() ? m.save(null, options).then(_.identity) : m;
 }));
};

Gist link: https://gist.github.com/julianitor/701c677279bac1529b88

要点链接:https://gist.github.com/julianitor/701c677279bac1529b88