Hintergrund
Tom Dale hat kürzlich angekündigt, dass "Embedded Loading jetzt zurück ist!" ist. Allerdings scheint es nur vollständig für das _laden_Szenario unterstützt zu werden. Es ist unklar, ob das serialisieren von eingebetteten Assoziationen noch in Entwicklung ist oder ob Benutzer erwartet werden, dies selbst umzusetzen, indem sie einen benutzerdefinierten Serializer erstellen.
Anforderungen
Das JSON für meine eingebettete Assoziation sieht so aus:
{
inputs: [
{
id: 1,
name: "Lieblingsfarbe",
type: "SelectInput",
options: {
choices: [ 'rot', 'grün', 'gelb' ]
}
},
{
id: 2,
name: "E-Mail",
type: "TextInput",
options: {}
}
]
}
Ich glaube, dass der "ember way" dies darzustellen ist, einen benutzerdefinierten Serializer zu erstellen, der mein JSON in Modelle wie diese umwandelt:
App.Choice = DS.Model.extend({
name: DS.attr( 'string' ),
input: DS.belongsTo( 'App.Input' )
});
App.Input = DS.Model.extend({
name: DS.attr( 'string' ),
type: DS.attr( 'string' ),
choices: DS.hasMany( 'App.Choice' )
});
Versuchte Lösung
Die folgende Lösung funktioniert größtenteils, allerdings fühlt es sich so an, als ob ich etwas falsch mache, weil ich so viel Code umgekehrt ingenieurge und untergeordnet habe.
Customizer.MyRESTAdapter = DS.RESTAdapter.extend({
dirtyRecordsForAttributeChange: function(dirtySet, record, attributeName, newValue, oldValue) {
if(record.constructor === Customizer.Choice) {
if(newValue === oldValue) { return; }
var input = null;
if (attributeName == 'name') {
input = record.get('input');
}
else if(attributeName == 'input') {
input = newValue;
}
if( input ) {
dirtySet.add( input );
}
}
else {
this._super(dirtySet, record, attributeName, newValue, oldValue);
}
},
dirtyRecordsForBelongsToChange: function(dirtySet, child, relationship) {
if(child.constructor === Customizer.Choice) {
var input = child.get( 'input' );
if( input ) {
dirtySet.add( input );
}
}
else {
this._super(dirtySet, child, relationship);
}
},
dirtyRecordsForHasManyChange: function(dirtySet, parent, relationship) {
this._super(dirtySet, parent, relationship);
}
});
Customizer.MyRESTSerializer = DS.RESTSerializer.extend({
init: function() {
this._super();
this.mappings.set( 'Customizer.Input', { choices: { embedded: 'load' } } );
},
extractEmbeddedHasMany: function(type, hash, key) {
if(type == Customizer.Input) {
if(!(hash['options'] && hash['options']['choices'])) { return null; }
var choices = [];
hash['options']['choices'].forEach(function(choice, i){
var choiceId = hash['id'] + '_' + i;
var inputId = hash['id'];
choices[i] = { id: choiceId, input_id: inputId, name: choice };
});
return choices;
}
return this._super(type, hash, key);
},
addHasMany: function(data, record, key, relationship) {
this._super(data, record, key, relationship);
if( key === 'choices' ) {
var choices = record.get('choices').map(function( choice ){
return choice.get( 'name' );
});
data['options'] = data['options'] || {};
data['options']['choices'] = choices;
}
}
});
Customizer.store = DS.Store.create({
revision: 10,
adapter: Customizer.MyRESTAdapter.create({
namespace: 'api/v1',
bulkCommit: false,
serializer: Customizer.MyRESTSerializer
})
})
Anfrage Für Feedback
- Ist dies der richtige Weg?
- Arbeitet das Ember-Team aktiv an einer besseren Lösung dafür?