【问题标题】:Best practice for saving an entire collection?保存整个集合的最佳实践?
【发布时间】:2011-06-28 04:55:09
【问题描述】:

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

【问题讨论】:

  • 添加新的 REST 资源,例如 ModelsArray

标签: jquery model-view-controller backbone.js backbone.js-collections


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

    我要在这里做错事,并引用维基百科关于proper RESTful practices 的内容:PUTexample.com/resources 应该用另一个集合替换整个集合。基于此,当我们不得不支持同时编辑多个项目时,我们写了这个合同。

    1. 客户端发送{"resources": [{resource1},{resource2}]}
    2. 服务器将整个集合替换为来自客户端的新信息,并在信息持久化后返回:{"resources": [{"id":1,...},{"id":2,...}]}

    我们在 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
    

    我认为这是 很多 更容易实现然后覆盖 Backbone.sync。对代码的一条评论,我们的集合总是子对象,这应该解释为什么每当一个对象被添加到集合中时代码设置一个“parent_id”,以及 URL 的根如何是父 URL。如果您有要修改的根级集合,则只需删除 @parent 业务即可。

    【讨论】:

    • +1,我仍然不确定为什么收藏没有保存选项。请注意,当我尝试使用您的上述代码时,我在@url() 电话中收到了Uncaught TypeError: Property 'url' of object [object Object] is not a function。将其作为属性而不是函数引用为我修复了该问题:@url
    • @MikeV 绝对-url 可以是属性或方法,所以你想使用适合你的那个。
    • @Crungmungus,嗯。我使用 CoffeeScript 是因为它很简洁,并且可以理解并且不会陷入困境。也许在某个时候我会用 JS 更新它,但你真的认为 CoffeeScript 让它更难理解吗?
    • 我遇到了与@MikeV 相同的错误。我认为这是保存 JSON 对象而不是模型的结果。我通过创建一个简单的包装模型解决了这个问题,它只定义了一个 url 属性,只是为了保存这个统一的集合。我的电话看起来像这样:Backbone.sync('update', new MyWrapperModel({ mythings: this.models })
    【解决方案3】:

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

    然后它应该调用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
        }
    });
    

    这里有另一种方法(使用模型来表示集合):"How" to save an entire collection in Backbone.js - Backbone.sync or jQuery.ajax?

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

    【讨论】:

      【解决方案4】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-06
        • 1970-01-01
        • 2010-10-18
        • 2010-09-18
        • 2016-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多