diff --git a/packages/-ember-data/tests/integration/identifiers/polymorphic-scenarios-test.ts b/packages/-ember-data/tests/integration/identifiers/polymorphic-scenarios-test.ts index a24244052ca..2e21124037d 100644 --- a/packages/-ember-data/tests/integration/identifiers/polymorphic-scenarios-test.ts +++ b/packages/-ember-data/tests/integration/identifiers/polymorphic-scenarios-test.ts @@ -61,7 +61,34 @@ module('Integration | Identifiers - single-table-inheritance polymorphic scenari store = owner.lookup('service:store'); }); - test(`Identity of polymorphic relations can change type`, async function(assert) { + test(`Identity of polymorphic relations can change type on first load`, async function(assert) { + const { owner } = this; + class TestAdapter extends Adapter { + shouldBackgroundReloadRecord() { + return false; + } + findRecord(_, __, id) { + return resolve({ + data: { + id, + type: 'ferrari', + attributes: { + color: 'red', + }, + }, + }); + } + } + owner.register('adapter:application', TestAdapter); + + const foundFerrari = await store.findRecord('car', '1'); + assert.strictEqual(foundFerrari.constructor.modelName, 'ferrari', 'We found the right type'); + + const cachedFerrari = await store.peekRecord('ferrari', '1'); + assert.strictEqual(cachedFerrari.constructor.modelName, 'ferrari', 'We cached the right type'); + }); + + test(`Identity of polymorphic relations can change type when in cache`, async function(assert) { const { owner } = this; const requests: RID[] = []; const expectedRequests = [ diff --git a/packages/store/addon/-private/identifiers/cache.ts b/packages/store/addon/-private/identifiers/cache.ts index f9e7af7db72..1dd4d6f3127 100644 --- a/packages/store/addon/-private/identifiers/cache.ts +++ b/packages/store/addon/-private/identifiers/cache.ts @@ -1,4 +1,5 @@ import { warn } from '@ember/debug'; +import { assign } from '@ember/polyfills'; import { DEBUG } from '@glimmer/env'; import coerceId from '../system/coerce-id'; @@ -343,6 +344,17 @@ export class IdentifierCache { let newId = coerceId(data.id); let existingIdentifier = detectMerge(this._cache.types, identifier, data, newId, this._cache.lids); + if (!existingIdentifier) { + // If the incoming type does not match the identifier type, we need to create an identifier for the incoming + // data so we can merge the incoming data with the existing identifier, see #7325 and #7363 + if (data.type && identifier.type !== normalizeModelName(data.type)) { + let incomingDataResource = assign({}, data); + // Need to strip the lid from the incomingData in order force a new identifier creation + delete incomingDataResource.lid; + existingIdentifier = this.getOrCreateRecordIdentifier(incomingDataResource); + } + } + if (existingIdentifier) { let keyOptions = getTypeIndex(this._cache.types, identifier.type); identifier = this._mergeRecordIdentifiers(keyOptions, identifier, existingIdentifier, data, newId as string);