2013-02-28 14 views
9

Mam trudny zapis relacji jeden-do-wielu w danych embera. Mam relację takiego:Dane Embera zapisujące relację

App.ParameterSet = DS.Model 
    name: DS.attr("string") 
    regions: DS.hasMany("App.Region") 

App.Region = DS.Model 
    name: DS.attr("string") 

Gdybym miał zrobić coś takiego:

parameterSet = App.ParameterSet.find(5) 
@transaction = @get("store").transaction() 
@transaction.add(parameterSet) 
region1 = App.Region.find(10) 
region2 = App.Region.find(11) 
parameterSet.set("name", "foo") 
parameterSet.get("regions").pushObject(region) 
@transaction.commit() 

Następnie chciałbym zobaczyć żądania PUT z ładunkiem tak:

api/ParameterSets/5 

{parameterSet: {name: "foo", regionIds:[10, 11]}} 

, ale zamiast tego otrzymuję:

{parameterSet: {name: "foo"}} 

Nie interesuje mnie relacja z powrotem od dziecka do rodzica, ale jeśli dodaję parameterSet: DS.belongsTo("App.ParameterSet") do modelu App.Region, otrzymam 2 żądania PUT do adresu URL regionów dla dwóch nowych relacji, które tak naprawdę nie są tym, czego chcę.

Sądzę, że jest to relacja wiele do wielu, ale nie jestem pewna, czy jest ona jeszcze obsługiwana, ale jakieś pomysły, jak osiągnąć to, co opisałem? Dzięki

Odpowiedz

8

Serializacja relacji hasMany jest obsługiwana metodą addHasMany() z json_serializer.js.

Poniższa notatka jest wliczone w source code:

Domyślne semantyka REST mają tylko dodać, posiada wiele relacji, jeśli jest osadzony. Jeśli relacja została początkowo załadowana przez identyfikator, zakładamy, że , która została wykonana jako optymalizacja wydajności, i która zmienia się na has-many powinna zostać zapisana jako zmiany klucza obcego na relacji child należy do .

Aby osiągnąć to, co chcesz, jedną z opcji jest wskazanie, że relacja powinna być osadzona w adapterze.

App.Store = DS.Store.extend({ 
    adapter: DS.RESTAdapter.extend({ 
    serializer: DS.RESTSerializer.extend({ 
     init: function() { 
     this._super(); 
     this.map('App.ParameterSet', { 
      regions: { embedded: 'always' } 
     }); 
     } 
    }) 
    }) 
}); 

Oczywiście teraz Twój back-end będzie musiał faktycznie osadzić JSON Associated regionów w JSON zestaw parametrów użytkownika. Jeśli chcesz zachować rzeczy takimi, jakie są, możesz po prostu zastąpić addHasMany() serializacją niestandardową.

App.Store = DS.Store.extend({ 
    adapter: DS.RESTAdapter.extend({ 
    serializer: DS.RESTSerializer.extend({ 
     addHasMany: function(hash, record, key, relationship) { 
     // custom ... 
     } 
    }) 
    }) 
}); 
+0

Wielkiego, dzięki, że bardzo pomaga – Charlie

+0

Jest to bardzo pomocne, dzięki! Myślę, że jest to bardzo krótkowzroczne założenie dla danych ember! – KOGI

+0

Jakie jest uzasadnienie dla tej "optymalizacji"? Widzę, że jest to optymalizacja podczas ładowania, ale w jaki sposób pomaga podczas zapisywania? Gdybym chciał dodać 100 obiektów potomnych do obiektu nadrzędnego, musiałbym dodać do każdego dziecka identyfikator nadrzędny i zapisać każde dziecko osobno (100 oddzielnych żądań POST/PUT), podczas gdy ja * mogłem * mieć właśnie dodał wszystkie 100 identyfikatorów do rodzica i zrobił jeden POST/PUT i zostało zrobione. – KOGI

2

nie jestem w stanie dodawać komentarze do odpowiedzi ahmacleod, ale to jest na miejscu z wyjątkiem, że zauważyłem, że rekord nadrzędny nie jest oznaczony jako brudne, gdy rekord dziecko jest modyfikowany. W przykładzie w pytaniu problem nie powstaje, ponieważ nazwa jest również modyfikowana w rekordzie nadrzędnym.

Ogólnie rzecz biorąc, jeśli zamierzasz zastosować drugą odpowiedź ahmacleod, musisz zastąpić metodę dirtyRecordsForHasManyChange na RESTAdapter. W przeciwnym razie addHasMany w serializatorze nigdy nie jest wywoływany, ponieważ rekord nie jest nawet oznaczony jako brudny.

istniejąca metoda wygląda następująco:

dirtyRecordsForHasManyChange: function(dirtySet, record, relationship) { 
    var embeddedType = get(this, 'serializer').embeddedType(record.constructor, relationship.secondRecordName); 

    if (embeddedType === 'always') { 
    relationship.childReference.parent = relationship.parentReference; 
    this._dirtyTree(dirtySet, record); 
    } 
}, 

Więc myślę, że warto coś takiego:

App.Store = DS.Store.extend({ 
    adapter: DS.RESTAdapter.extend({ 
    dirtyRecordsForHasManyChange: function(dirtySet, record, relationship) { 
     relationship.childReference.parent = relationship.parentReference; 
     this._dirtyTree(dirtySet, record); 
    }, 

    serializer: DS.RESTSerializer.extend({ 
     addHasMany: function(hash, record, key, relationship) { 
     // custom ... 
     } 
    }) 
    }) 
}); 
+0

Nie testowałem tego, ale wygląda na dobry połów. – ahmacleod

Powiązane problemy