2011-11-21 4 views
6

TL; DR:サーバーからモデルコレクション全体をポーリングしている場合、変更された属性を各モデルにマージし、追加/削除したモデルをコレクションに追加/削除する方法を教えてください?私の基幹アプリでサーバーの応答を伴うバックボーンコレクションをマージする

、私はモデルのコレクション全体をポーリングしています。

myCollection.reset(server_response); 

これの唯一の問題は、それが古いモデルを取り除くことで、利益をなくすの種類:私は、私は基本的にはそう、私はモデルの配列を取得するたびにresetを呼び出していますBackbone.Collectionを持っていますモデル上のイベント。これは当然のresetの目的ですが、私は何をしたいコレクションをモデルの変更属性を変更し、対応していないモデルを削除し、それに応答していたモデルを追加するだけでなくです。

基本的に私は、データのマージの並べ替えをしたいです。すでに反応して、コレクションしているモデルの場合

、私は、プロセス内のchangeイベントをトリガ、私はちょうどmodel.set(attributes)を行うことができますし、それが実際に変更ものだけをINGのsetの世話をすると信じています。これは素晴らしい。

しかし、どのように私はいない応答ではなく、コレクションでは、モデルはすでに対応してではなく、コレクションにあった場合、およびその逆を扱うのですか?

私の提案された解決策

バックボーンはすでにこれを行う方法を持っている場合、私は知らない、と私は私が求めている理由である過度に複雑することができるが、私はメソッドを作成するので、その後を考えていました私のコレクションにはserver_responseが渡されます。

idの属性のすべてがserver_response、およびコレクションの中のモデルのidのすべての属性を取得します。

応答id年代の差 - コレクションが=モデルを添加なり、そしてその逆モデルを除去することになります。それらのモデルをそれぞれコレクションに追加して削除します。

idの両方のセットの共通部分が修正されたモデルになるので、idを反復して、単にcollection.get(id).set(attributes)を実行します。 pseudocoffeescriptで

merge: (server_response) => 
    response_ids = _.pluck(server_response, 'id') 
    collection_ids = @pluck('id') 

    added = _.difference(response_ids, collection_ids) 

    for add in added 
    @add(_.find(server_response, (model) -> 
     return model.id == add 
    )) 

    removed = _.difference(collection_ids, response_ids) 

    for remove in removed 
    @remove(@get(remove)) 

    changed = _.intersection(response_ids, collection_ids) 

    for change in changed 
    @get(change).set(_.find(server_response, (model) -> 
     return model.id == change 
    )) 
+0

*> pseudocoffeescriptで:*神ああ。 –

+0

それは実際にcoffeescriptだ、私はまだhahaをテストしていないので、私は疑似を意味した。 –

答えて

9

この技術は、時には有用です。次の方法でCollectionを拡張します。これはあなたが探していることを行うはずです。それはコーヒーではありませんが、簡単に移植することができます。楽しい!

// Take an array of raw objects 
// If the ID matches a model in the collection, set that model 
// If the ID is not found in the collection, add it 
// If a model in the collection is no longer available, remove it 
freshen: function (objects) { 
    var model; 
    // Mark all for removal 

    this.each(function (m) { 
     m._remove = true; 
    }); 

    // Apply each object 
    _(objects).each(function (attrs) { 
     model = this.get(attrs.id); 
     if (model) { 
      model.set(attrs); // existing model 
      delete model._remove 
     } else { 
      this.add(attrs); // new model 
     } 
    }, this); 

    // Now check for any that are still marked for removal 
    var toRemove = this.filter(function (m) { 
     return m._remove; 
    }) 

    _(toRemove).each(function (m) { 
     this.remove(m); 
    }, this); 
    this.trigger('freshen', this); 
} 
+0

クール感謝maxl0rd。私が行っていたものと似ていますが、これから使用できるいくつかのもの、例えばフラグを削除しているものがあります。私はちょっと待って、他の答えが出てこないか見てみよう。私は正しいとあなたの印をつけるだろう。 –

+0

良いこと。 「マークとスイープ」は少し醜いですが、大規模なコレクションではおそらく最も効率的なアプローチです。 – maxl0rd

+0

非常にクール&有用なおかげで。私はコレクションへのローカル追加を維持し、クライアント上の任意の状態を保持するためにわずかな変更を加えました。あなたはその変更が好きかもしれません。 'm._remove = true;'を 'if(!m.isNew())m._remove = true;に変更するだけです。 – Subimage

関連する問題