-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BUGFIX] enable lazy-relationship payloads to work with polymorphic relationships #5230
Changes from 11 commits
6ce71be
5fd015d
65b2562
2ba9af4
009c125
b8589d6
e137112
f3f0323
b953a79
3633a5d
f63d420
5be8b95
5c13ece
0f22ccb
cb4c533
cdb7b17
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -156,7 +156,7 @@ export default class RelationshipPayloadsManager { | |
relationshipPayloads.get('user', 'hobbies') === relationshipPayloads.get('hobby', 'user'); | ||
|
||
The signature has a somewhat large arity to avoid extra work, such as | ||
a) string maipulation & allocation with `modelName` and | ||
a) string manipulation & allocation with `modelName` and | ||
`relationshipName` | ||
b) repeatedly getting `relationshipsByName` via `Ember.get` | ||
|
||
|
@@ -172,7 +172,28 @@ export default class RelationshipPayloadsManager { | |
return this._initializeRelationshipPayloads(modelName, relationshipName, modelClass, relationshipsByName); | ||
} | ||
|
||
return this._cache[key]; | ||
let cache = this._cache[key]; | ||
|
||
if (cache === undefined) { | ||
let inverseMeta = modelClass.inverseFor(relationshipName, this._store); | ||
|
||
if (inverseMeta) { | ||
let inverseRelationshipMeta = get(inverseMeta.type, 'relationshipsByName').get(inverseMeta.name); | ||
let baseModelName = inverseRelationshipMeta.type; | ||
|
||
if (baseModelName !== modelName) { | ||
let baseKey = `${baseModelName}:${relationshipName}`; | ||
cache = this._cache[baseKey]; | ||
|
||
if (cache !== undefined) { | ||
cache.addPolymorphicType(baseModelName, modelName); | ||
this._cache[key] = cache; | ||
} | ||
} | ||
} | ||
} | ||
|
||
return cache; | ||
} | ||
|
||
/** | ||
|
@@ -184,18 +205,24 @@ export default class RelationshipPayloadsManager { | |
_initializeRelationshipPayloads(modelName, relationshipName, modelClass, relationshipsByName) { | ||
let relationshipMeta = relationshipsByName.get(relationshipName); | ||
let inverseMeta = modelClass.inverseFor(relationshipName, this._store); | ||
|
||
let selfIsPolymorphic = relationshipMeta.options !== undefined && relationshipMeta.options.polymorphic === true; | ||
let baseModelName = modelName; | ||
let inverseModelName; | ||
let inverseRelationshipName; | ||
let inverseRelationshipMeta; | ||
let inverseIsPolymorphic = false; | ||
let existingPolymorphicCache; | ||
|
||
// figure out the inverse relationship; we need two things | ||
// a) the inverse model name | ||
//- b) the name of the inverse relationship | ||
// b) the name of the inverse relationship | ||
if (inverseMeta) { | ||
inverseRelationshipName = inverseMeta.name | ||
inverseRelationshipName = inverseMeta.name; | ||
inverseModelName = relationshipMeta.type; | ||
inverseRelationshipMeta = get(inverseMeta.type, 'relationshipsByName').get(inverseRelationshipName); | ||
inverseIsPolymorphic = inverseRelationshipMeta.options !== undefined && inverseRelationshipMeta.options.polymorphic === true; | ||
|
||
baseModelName = inverseRelationshipMeta.type; | ||
} else { | ||
// relationship has no inverse | ||
inverseModelName = inverseRelationshipName = ''; | ||
|
@@ -204,14 +231,29 @@ export default class RelationshipPayloadsManager { | |
|
||
let lhsKey = `${modelName}:${relationshipName}`; | ||
let rhsKey = `${inverseModelName}:${inverseRelationshipName}`; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. as discussed out of band, in both cases we want the key to be the model name defined by the inverse relationship, when an inverse relationship exists There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so we should always create |
||
let lhsBaseKey = `${baseModelName}:${relationshipName}`; | ||
|
||
if (inverseIsPolymorphic === true) { | ||
existingPolymorphicCache = this._cache[rhsKey]; | ||
} else if (selfIsPolymorphic) { | ||
existingPolymorphicCache = this._cache[lhsBaseKey]; | ||
} | ||
|
||
if (existingPolymorphicCache !== undefined) { | ||
this._cache[lhsKey] = existingPolymorphicCache; | ||
|
||
existingPolymorphicCache.addPolymorphicType(baseModelName, modelName); | ||
|
||
return existingPolymorphicCache; | ||
} | ||
|
||
// populate the cache for both sides of the relationship, as they both use | ||
// the same `RelationshipPayloads`. | ||
// | ||
// This works out better than creating a single common key, because to | ||
// compute that key we would need to do work to look up the inverse | ||
// | ||
return this._cache[lhsKey] = | ||
return this._cache[lhsBaseKey] = this._cache[lhsKey] = | ||
this._cache[rhsKey] = | ||
new RelationshipPayloads( | ||
this._store, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add comments here as to what we are doing