diff --git a/packages/ember-data/lib/serializers/rest-serializer.js b/packages/ember-data/lib/serializers/rest-serializer.js index 768bdcd1f8e..a987ffa6202 100644 --- a/packages/ember-data/lib/serializers/rest-serializer.js +++ b/packages/ember-data/lib/serializers/rest-serializer.js @@ -145,10 +145,19 @@ var RESTSerializer = JSONSerializer.extend({ included: [] }; - let modelClass = store.modelFor(modelName); - let serializer = store.serializerFor(modelName); + let primaryModelClass = store.modelFor(modelName); + let primarySerializer = store.serializerFor(modelName); arrayHash.forEach((hash) => { + let serializer, modelClass; + // Support polymorphic records in async relationships + if (hash.type && store._hasModelFor(this.modelNameFromPayloadKey(hash.type))) { + serializer = store.serializerFor(hash.type); + modelClass = store.modelFor(hash.type); + } else { + serializer = primarySerializer; + modelClass = primaryModelClass; + } let { data, included } = serializer.normalize(modelClass, hash, prop); documentHash.data.push(data); if (included) { @@ -239,7 +248,16 @@ var RESTSerializer = JSONSerializer.extend({ ``` */ if (isPrimary && Ember.typeOf(value) !== 'array') { - let {data, included} = this.normalize(primaryModelClass, value, prop); + var serializer, modelClass; + // Support polymorphic records in async relationships + if (value.type && store._hasModelFor(this.modelNameFromPayloadKey(value.type))) { + serializer = store.serializerFor(value.type); + modelClass = store.modelFor(value.type); + } else { + serializer = this; + modelClass = primaryModelClass; + } + let {data, included} = serializer.normalize(modelClass, value, prop); documentHash.data = data; if (included) { documentHash.included.push(...included); diff --git a/packages/ember-data/tests/integration/serializers/rest-serializer-test.js b/packages/ember-data/tests/integration/serializers/rest-serializer-test.js index fd1b6fec768..30ffa0f7383 100644 --- a/packages/ember-data/tests/integration/serializers/rest-serializer-test.js +++ b/packages/ember-data/tests/integration/serializers/rest-serializer-test.js @@ -17,7 +17,9 @@ module("integration/serializer/rest - RESTSerializer", { superVillain: DS.belongsTo('super-villain', { async: false }), name: DS.attr('string') }); - YellowMinion = EvilMinion.extend(); + YellowMinion = EvilMinion.extend({ + eyes: DS.attr('number') + }); DoomsdayDevice = DS.Model.extend({ name: DS.attr('string'), evilMinion: DS.belongsTo('evil-minion', { polymorphic: true, async: true }) @@ -461,6 +463,81 @@ test('serializeIntoHash uses payloadKeyFromModelName to normalize the payload ro }); }); +test('normalizeResponse with async polymorphic belongsTo', function() { + env.registry.register('serializer:application', DS.RESTSerializer.extend({ + isNewSerializerAPI: true + })); + var store = env.store; + env.adapter.findRecord = () => { + return { + doomsdayDevices: [{ + id: 1, + name: "DeathRay", + links: { + evilMinion: '/doomsday-device/1/evil-minion' + } + }] + }; + }; + + env.adapter.findBelongsTo = () => { + return { + evilMinion: { + id: 1, + type: 'yellowMinion', + name: 'Alex', + eyes: 3 + } + }; + }; + run(function() { + store.findRecord('doomsday-device', 1).then((deathRay) => { + return deathRay.get('evilMinion'); + }).then((evilMinion) => { + equal(evilMinion.get('eyes'), 3); + }); + }); +}); + +test('normalizeResponse with async polymorphic hasMany', function() { + SuperVillain.reopen({ evilMinions: DS.hasMany('evil-minion', { async: true, polymorphic: true }) }); + env.registry.register('serializer:application', DS.RESTSerializer.extend({ + isNewSerializerAPI: true + })); + var store = env.store; + env.adapter.findRecord = () => { + return { + superVillains: [{ + id: "1", + firstName: "Yehuda", + lastName: "Katz", + links: { + evilMinions: '/super-villain/1/evil-minions' + } + }] + }; + }; + + env.adapter.findHasMany = () => { + return { + evilMinion: [{ + id: 1, + type: 'yellowMinion', + name: 'Alex', + eyes: 3 + }] + }; + }; + run(function() { + store.findRecord('super-villain', 1).then((superVillain) => { + return superVillain.get('evilMinions'); + }).then((evilMinions) => { + ok(evilMinions.get('firstObject') instanceof YellowMinion); + equal(evilMinions.get('firstObject.eyes'), 3); + }); + }); +}); + test("normalizeResponse can load secondary records of the same type without affecting the query count", function() { var jsonHash = { comments: [{ id: "1", body: "Parent Comment", root: true, children: [2, 3] }],