2011-11-21 17 views
6

TL; DR: Si estoy sondeando toda la colección de modelos del servidor, ¿cómo puedo fusionar los atributos modificados en cada modelo y agregar/eliminar modelos agregados/eliminados de la colección ?fusionar colección principal con respuesta del servidor

En mi aplicación de red troncal, estoy buscando toda la colección de modelos. He una Backbone.Collection que estoy básicamente llamando reset en cada vez que conseguir la gama de modelos, por lo que:

myCollection.reset(server_response); 

El único problema con esto es que se deshace de los antiguos modelos, tipo de eliminar el beneficio de eventos en un modelo. Este es el propósito de reset, por supuesto, pero lo que quiero hacer es modificar los atributos modificados de los modelos y eliminar los modelos que no están en la respuesta, y agregar los modelos que estaban en la respuesta pero no la colección.

Esencialmente quiero un tipo de combinar de los datos.

Para los modelos que se encuentran en la respuesta y en la colección ya, creo que sólo puede hacer model.set(attributes) y que se encarga de set ing sólo los que realmente cambiaron, lo que provocó las change eventos en el proceso. Esto es genial.

¿Pero cómo manejo los casos donde los modelos estaban en la respuesta pero no en la colección ya, y viceversa, no en la respuesta pero en la colección?

Mi Solución propuesta

No sé si la columna vertebral ya tiene una forma de hacer esto, y yo puedo ser complicar excesivamente por lo que estoy pidiendo, pero yo estaba pensando a continuación de la creación de un método en mi colección que se pasa el server_response.

Obtendría todos los atributos id del server_response, y todos los atributos id de los modelos que ya están en la colección.

La diferencia de id en respuesta - colección sería = modelos agregados, y viceversa se eliminarán los modelos. Agregue y elimine esos modelos, respectivamente, de la colección.

La intersección de los dos conjuntos de id serían los modelos modificados, por lo tanto, repita estos id y simplemente haga un collection.get(id).set(attributes).

En 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

*> En pseudocoffeescript: * Oh dios. –

+0

Es en realidad coffeescript, quise decir pseudo porque aún no lo he probado jaja. –

Respuesta

9

Esta técnica es útil a veces. Extendemos la Colección con el siguiente método. Esto debería hacer lo que estás buscando. No está en el café, pero podrías portarlo fácilmente. ¡Disfrutar!

// 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

Cool gracias maxl0rd.Parece similar a lo que tenía en mente, pero hay algunas cosas que puedo usar a partir de esto, como el indicador de eliminación. Esperaré un poco para ver si aparece alguna otra respuesta, marcaré la tuya como correcta :) –

+0

Buen trato. La "marca y barrido" es un poco feo, pero probablemente el enfoque más eficiente en grandes colecciones. – maxl0rd

+0

Gracias muy interesantes y útiles. Agregué un ligero cambio para mantener las adiciones locales a la colección y preservar cualquier estado en el cliente. Es posible que le guste el cambio. Simplemente cambie 'm._remove = true;' a 'if (! M.isNew()) m._remove = true;' – Subimage

Cuestiones relacionadas