2012-09-10 10 views
6

Myślę, że mam dość prosty problem, który jest trudny do sformułowania i dlatego trudno znaleźć rozwiązanie. Konfiguracja:Przesyłaj/inicjalizuj podmodele modelu szkieletowego

  • PathCollection jest Backbone.Collection ścieżek
  • ścieżka jest Backbone.Model zawierający NodeCollection (który jest Backbone.Collection) i EdgeCollection (który jest Backbone.Collection).

Kiedy pobrać PathCollection

paths = new PathCollection() 
paths.fetch() 

oczywiście Ścieżki się instancja. Brakuje mi jednak miejsca, w którym mogę zezwolić na ścieżkę do tworzenia swoich podmodeli z skrótów atrybutów. Naprawdę nie mogę użyć parse, prawda? Zasadniczo im szukasz punktu wejścia dla modelu, gdy jego instancji i zestaw z atrybutami. Czuję, że musi to być jakaś konwencja.

+1

Czy próbowałeś użyć metody [initialize] (http://documentcloud.github.com/backbone/#Model-constructor)? – Jack

+0

będzie działać, gdy zainicjuję kolekcję, ale co, jeśli samodzielnie zdobędę ścieżkę? Kiedy przyniosę Ścieżkę, już ją zainicjowałem, prawda? – nambrot

+0

Aby wymyślić słowo, myślę, że chcesz przeczytać więcej o "modelach zagnieżdżonych i kolekcjach". – jmk2142

Odpowiedz

24

Napisałem kilka odpowiedzi dotyczących używania parse() i set() do tworzenia instancji i wypełniania pod-modeli i sub-kolekcji (danych zagnieżdżonych). Jednak nie widziałem naprawdę wyczerpującej odpowiedzi, która konsoliduje niektóre z wielu praktyk, które widziałem. Mam tendencję do wędrowania trochę, kiedy piszę dużo, więc mogę trochę odejść, ale może to być przydatne dla osób przechodzących przez podobne problemy.

Istnieje kilka sposobów, aby to zrobić. Używanie parse() jest jednym z nich. Manipulowanie set() jest kolejnym. Tworzenie ich w twoim initialize() jest kolejnym. Robiąc to wszystko poza modelem ścieżki, jest inny (na przykład path = new Path(); path.nodes = new NodeCollection(); itp.)

Drugą kwestią jest to. Czy chcesz, aby węzły i kolekcje krawędzi były atrybutami modelu? Lub właściwości modelu?

Och tak wielu wyborów. Dużo swobody, ale czasami (ku naszej frustracji) utrudnia określenie "właściwej drogi".

Ponieważ pojawia się to często, mam zamiar zrobić długi post i przejść przez te jeden po drugim. Więc weź mnie ze sobą, kiedy będę aktualizować tę odpowiedź.

Robi to poza modelami - proste i prosto do przodu

Zazwyczaj jest to łatwy sposób, aby dodać zagnieżdżone modele i kolekcje, kiedy tylko jest to potrzebne w konkretnym modelu lub kolekcji.

path = new PathModel(); 

path.nodes = new NodeCollection(); 
path.edge = new EdgeCollection(); 

// Continue to set up the nested data URL, etc. 

Jest to najprostszy sposób i działa dobrze, gdy masz do czynienia z jednym modeli czasowych i zbiorów, które nie muszą mieć definicji. Chociaż można łatwo tworzyć te modele w pewnej metodzie (na przykład metodzie widoku), która tworzy ten obiekt, zanim cokolwiek z nim zrobi.

Korzystanie initialize() Sub model/kolekcje w każdym modelu

Jeśli wiesz, że każdy przypadek pewnego modelu będą zawsze mieć pod-modelu lub sub-kolekcji, najprostszym sposobem, aby ustawić rzeczy byłoby korzystać z funkcji initialize().

Na przykład, weźmy model Path:

Path = Backbone.Model.extend({ 
    initialize: function() { 
     this.nodes = new NodeCollection(); 
     this.paths = new PathCollection(); 

     // Maybe assign a proper url in relation to this Path model 
     // You might even set up a change:id listener to set the url when this 
     // model gets an id, assuming it doesn't have one at start. 
     this.nodes.url = this.id ? 'path/' + this.id + '/nodes' : undefined; 
     this.paths.url = this.id ? 'path/' + this.id + '/paths' : undefined; 
    } 
}); 

Teraz sub-kolekcje mogą być pobierane jak path.nodes.fetch() i skieruje do odpowiedniego adresu URL. Bułka z masłem.

Korzystanie parse() dla instancji i ustawienie subdanych

Być może, robi się trochę bardziej skomplikowane, jeśli nie chcą przyjąć każdy model będzie mieć węzły i kolekcje krawędzi. Może chcesz zagnieżdżone modele/kolekcje tylko wtedy, gdy fetch() odsyła takie dane. Jest tak w przypadku, gdy przydaje się używanie parse().

Rzecz z parse() polega na tym, że pobiera JAKĄKOLWIEK odpowiedź serwera json i może poprawnie nazwać przestrzeń i poradzić sobie z nią przed przekazaniem jej do funkcji modelu set(). Możemy więc sprawdzić, czy zawiera on dane modelu lub danych nieprzetworzonych kolekcji, i poradzić sobie z nimi przed zmniejszeniem odpowiedzi do atrybutów modelu nadrzędnego.

Na przykład, może z naszego serwera mamy tej odpowiedzi:

// Path model JSON example with nested collections JSON arrays 
{ 
    'name':'orange site', 
    'url':'orange.com', 
    'nodes':[ 
     {'id':'1', 'nodeColor':'red'}, 
     {'id':'2', 'nodeColor':'white'}, 
     {'id':'3', 'nodeColor':'blue'} 
    ], 
    'edge':[ 
     {'id':'1', 'location':'north'}, 
     {'id':'1', 'location':'south'}, 
     {'id':'1', 'location':'east'} 
    ] 
} 

z domyślnym parse() Backbone to będzie pożerać się i przypisać swoją ścieżkę modelu atrybutów węzły "oraz„krawędzi”z tablicy() danych (nie kolekcje). Dlatego chcemy się upewnić, że nasz parse() zajmuje się tym właściwie.

parse: function(response) { 

    // Check if response includes some nested collection data... our case 'nodes' 
    if (_.has(response, 'nodes')){ 

     // Check if this model has a property called nodes 
     if (!_.has(this, 'nodes')) { // It does not... 
      // So instantiate a collection and pass in raw data 
      this.nodes = new NodeCollection(response.nodes); 
     } else { 
      // It does, so just reset the collection 
      this.nodes.reset(response.nodes); 
     } 

     // Assuming the fetch gets this model id 
     this.nodes.url = 'path/' + response.id + '/nodes'; // Set model relative URL 

     // Delete the nodes so it doesn't clutter our model attributes 
     delete response.nodes; 
    } 

    // Same for edge... 

    return response; 
} 

Można również używać własnego set() radzić sobie ze swoimi cząstkowych danych. Po długich zwrotach między tymi operacjami lepiej jest manipulować set() lub robić to w parse(). Postanowiłem, że jeszcze bardziej lubię używać parse(). Ale jestem otwarty na myśli innych ludzi na ten temat.

Korzystanie set() radzić sobie ze swoimi subdanych

Podczas parse() opiera się albo pobierania danych lub przekazywania danych do kolekcji z opcją parse:true niektórzy ludzie uważają, że preferencyjna aby zmienić funkcję set(). Ponownie, nie jestem pewien, czy istnieje właściwy wybór, ale oto jak to zadziała.

set: function(attributes, options) { 
    // If we pass in nodes collection JSON array and this model has a nodes attribute 
    // Assume we already set it as a collection 
    if (_.has(attributes, 'nodes') && this.get("nodes")) { 
     this.get('nodes').reset(attributes.nodes); 
     delete attributes.nodes; 
    } else if (_.has(attributes, 'nodes') && !this.get('nodes')) { 
     this.set('nodes', new NodeCollection(attributes.nodes)); 
     delete attributes.nodes; 
    } 

    return Backbone.Model.prototype.set.call(this, attributes, options); 
} 

Więc jeśli już mamy atrybut i jest to zbiór, my go reset(). Jeśli mamy atrybut, ale nie jest to kolekcja, tworzymy go. Ważne jest, aby poprawnie przetłumaczyć macierz subdanych JSON w kolekcję przed przekazaniem jej do prototypu set(). Backbone, nie interpretuje tablicy JSON jako kolekcji, a otrzymasz tylko prostą tablicę.

Więc w muszli orzechowej, masz wiele opcji, jak się poruszać. Ponownie, obecnie faworyzuję mieszankę używania initialize(), gdy wiem, że coś zawsze będzie miało te pod-modele/kolekcje i parse(), gdy sytuacja wywołuje tylko możliwe zagnieżdżone dane w połączeniach fetch().

Odnośnie tego pytania ...(O tak, było pytanie)

Możesz pozwolić Path na tworzenie pod-modeli z hasza na różne sposoby. Właśnie dałem ci 4. Możesz użyć analizy, jeśli chcesz, jeśli wiesz, że masz zamiar być fetch() modelem ścieżki LUB może nawet ścieżkąCollection ... pathCollection.fetch({parse:true}) Czy istnieje konwencja? Może, może nie. Lubię korzystać z kombinacji sposobów w zależności od kontekstu, w którym myślę, że będę używał modeli/kolekcji.

Jestem bardzo otwarty na dyskusję na temat niektórych z tych praktyk i tego, czy są dobre, czy złe. To tylko wiele rozwiązań, z jakimi spotkałem się na Stack i wcielone w moje własne nawyki pracy i wydaje mi się, że działają dla mnie dobrze. :-)

Napij się kawy i klepnij po plecach, to było długie czytanie.

Powiązane problemy