2011-11-21 11 views
6

TL; DR: Jeśli wybieram całą kolekcję modeli z serwera, jak scalić zmienione atrybuty w każdym modelu i dodać/usunąć dodane/usunięte modele z kolekcji ?Scalenie kolekcji kręgosłupa z odpowiedzią serwera

W mojej aplikacji szkieletowej wybieram dla całej kolekcji modeli. Mam Backbone.Collection, że jestem po prostu dzwoniąc reset w każdym czasie pojawia się szereg modeli, więc:

myCollection.reset(server_response); 

Jedyny problem polega na tym, że pozbywa się starych modeli, rodzaj eliminacji korzyści wydarzenia na modelu. Jest to oczywiście cel z zakresu reset, ale chcę tylko zmodyfikować zmienione atrybuty modeli i usunąć modele spoza zakresu odpowiedzi, a także dodać modele, które były w odpowiedzi, ale nie kolekcje.

Zasadniczo chcę pewnego rodzaju scalić danych.

Dla modeli, które znajdują się w odpowiedzi i już kolekcji, wierzę, że mogę po prostu zrobić model.set(attributes) i dba o set ing tylko te, które naprawdę się zmieniły, wyzwalając change wydarzeń w tym procesie. To jest świetne.

Ale jak obsługiwać przypadki, w których modele były w odpowiedzi, ale już nie w kolekcji, i na odwrót, nie w odpowiedzi, ale w kolekcji?

My Proponowane rozwiązanie

ja nie wiem, czy kręgosłup ma już sposób to zrobić, a ja może być overcomplicating dlatego pytam, ale myślał wtedy o stworzeniu metody na mojej kolekcji, która przechodzi server_response.

Otrzyma wszystkie atrybuty z server_response i wszystkie atrybuty id modeli już w kolekcji.

Różnica w odpowiedziach na id - kolekcja = modele dodane i na odwrót zostaną usunięte modele. Dodaj i usuń te modele odpowiednio z kolekcji.

Przecięcie obu zestawów id jest zmodyfikowanymi modelami, dlatego należy wykonać iterację poprzez te id i po prostu wykonać collection.get(id).set(attributes).

W 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

*> W pseudocoffeescript: * O Boże. –

+0

To właściwie coffeescript, miałem na myśli pseudo, ponieważ nie przetestowałem go jeszcze haha. –

Odpowiedz

9

Technika ta jest przydatna czasem. Rozszerzamy kolekcję o następującą metodę. To powinno zrobić to, czego szukasz. Nie ma go w kawie, ale można go łatwo przesłać. Cieszyć się!

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

Fajne dzięki maxl0rd.Wydaje się podobne do tego, co miałem, ale są pewne rzeczy, które mogę z tego użyć, takie jak flaga usuwania. Poczekam trochę, żeby zobaczyć, czy pojawią się jakieś inne odpowiedzi, które oznaczyłbym jako poprawne :) –

+0

Dobra oferta. "Marka i zamiatanie" jest trochę brzydka, ale prawdopodobnie najbardziej skuteczne podejście do dużych kolekcji. – maxl0rd

+0

Bardzo fajne i przydatne dzięki. Dodałem jedną niewielką zmianę, aby zachować lokalne dodatki do kolekcji i zachować dowolny stan na kliencie. Możesz polubić zmianę. Po prostu zmień 'm._remove = true;' na 'if (! M.isNew()) m._remove = true;' – Subimage

Powiązane problemy