Backbone.js集合upsert?

时间:2012-03-09 19:51:55

标签: backbone.js

我正在使用Backbone.js构建应用程序。我的一些服务器端API将在特定时间后返回所有新的或更改的模型。其中一些对象对我的收藏可能是新的,所以我可以添加它们。其他可能已经存在,在这种情况下,我想更新现有的模型。所以基本上我正在寻找upsert(更新或插入)功能。

这类似于0.9.0中添加的{add:true}选项,除了我还想要更新。

有一种简单/已知的方法可以做到这一点吗?更新代码似乎并不难,但我不想重新发明轮子。

2 个答案:

答案 0 :(得分:5)

我用通用方法解决了这种情况:

App.Utils = {
  refreshCollection: function( collection, collectionJSON ){
    // update/add
    _( collectionJSON ).each( function( modelJSON ) {
      var model = collection.get( modelJSON.id );
      if( model ) {
        model.set( modelJSON );
      } else {
        collection.add( modelJSON );
      }
    });

    // remove
    var model_ids_to_keep     = _( collectionJSON ).pluck( "id" );
    var model_ids             = collection.pluck( "id" );
    var model_ids_to_remove   = _( model_ids ).difference( model_ids_to_keep )

    _( model_ids_to_remove ).each( function( model_id_to_remove ){
      collection.remove( model_id_to_remove );
    });
  },
}

PARAMS

  • collection:是一个Backbone.Collection
  • collectionJSON:是一个包含哈希样式的模型数据的数组。典型的JSON响应。

我确信它可以进行优化,尤其是删除部分。但由于我仍在进行测试,因此可读性我保持这样。

使用示例

// code simplified and no tested
var VolatileCollection = Backbone.Collection.extend({
  // url:
  // model:
  // so on ... 
})

var PersistentCollection = Backbone.Collection.extend({
  // url: not needed due this Collection is never synchronized or changed by its own
  //   change the VolatileCollection instead, all changes will be mirrored to this Collection
  //   through events
  // model: the same

  initialize: function( opts ){
    this.volatileCollection = opts.volatileCollection;
    this.volatileCollection.on( "reset", this.update, this );
    this.volatileCollection.on( "change", this.update, this );
  }

  update: function(){
    App.Utils.refreshCollection( this, this.volatileCollection.toJSON() );
  }
})

var volatileCollection = new VolatileCollection();
var persistentCollection = new PersistentCollection({ volatileCollection: volatileCollection });

volatileCollection.fetch();

答案 1 :(得分:3)

注意:这个答案是为Backbone v0.9编写的。从那时起,Backbone v1.0已经发布,其中包含collection.set()描述的//**upsert** takes models and does an update-or-insert operation on them //So models that already exist are updated, and new models are added upsert: function (models, options) { var self = this; options || (options = {}); models = _.isArray(models) ? models.slice() : [models]; var addModels = []; _.each(models, function (newModel) { var n = self._prepareModel(newModel, options); var existingModel = self.get(n.id); if (existingModel) { existingModel.set(n, options); } else { addModels.push(n); } }); if (!_.isEmpty(addModels)) { self.add(addModels, options); } } 方法。这可能是一个更好的解决方案。

周末我将自己的版本整合在一起。我会把它放在这里以防其他人找到这个帖子,但我仍然很高兴看到任何其他可能存在的解决方案。

我通过修改Backbone.js源来做到这一点,这不一定是个好主意,但它很容易。有两个更改,首先将此函数添加到Backbone.Collection原型:

collection[options.add ? 'add' : (options.upsert ? "upsert" : 'reset')](collection.parse(resp, xhr), options);

然后修改Backbone.Collection.fetch()函数中的一行来读取:

fetch({upsert:true})

这允许您致电{{1}}以获取我正在寻找的行为。