There are several types of relationships.
- OneToMany
- OneToOne
- OneToNone
- ManyToNone
A OneToMany relationship has a Set of members and a link to the belongsTo. Each member and the belongsTo has a link back to the relationship. The member links can change.
A ManyToNone relationship has a Set of members and a link to the belongsTo. The belongsTo has a link back to the relationship. The link doesn't change.
A OneToOne relationship has a Set of members. Each member has a link back to the relationships. Either of the links may change.
A OneToNone relationship has a member and a belongsTo. The member has a link back to the relationship.
When a record is created for the first time, the kind of each relationship is determined. This determination is based on the kind of the relationship and the kind of its inverse.
These relationships are represented on one or more records by ManyArrays and belongsTo computed property caches.
Parameters: name, newRecord
- let rel be
record.relationshipFor(name) rel.removeMember(record)- If
newValueexists:- let newRel be
record.relationshipFor(name, newRecord) - Call
newRel.addMember(record)on the relationship
- let newRel be
The abstraction is that a belongs-to relationship represents membership in a has-many set. In some cases (OneToNone), there is no actual has-many set, but the relationship implements the same hooks.
In some cases, the relationship may become unlinked when removeMember is called and linked to a new relationship when relationshipFor is called.
Parameters: name, position, member
- let rel be
record.relationshipFor(name) rel.addMember(member, position)
The relationships that represent a ManyArray are never unlinked from the primary record during these steps.
Parameters: name, position
- let rel be
record.relationshipFor(name) rel.removeMember(member, position)
Parameters: record, data
Optional Parameter: inverse
inverseis passed along if the record was looked up through a relationship (for examplerecord.fetch(name)) because the relationship value is often not provided in payloads.
- For each relName in
record's relationships:- let rel be
record.relationshipFor(relName, inverse)
- let rel be
- let myKind be the kind of the
namerelationship onrecord - let inverseKind, inverseName be the kind and name of the inverse of the
namerelationship - Let RelationshipType be the result of getting from the registered map of relationship types with myKind and inverseKind as keys.
- Return
RelationshipType.create(name, record, value)
| Key A | Key B | Result |
|---|---|---|
| hasMany | belongsTo | ManyToOne |
| belongsTo | hasMany | OneToMany |
| hasMany | null | ManyToNone |
| belongsTo | null | OneToNone |
| belongsTo | belongsTo | OneToOne |
Note: ManyToOne is just a wrapper that takes the arguments in reverse position and returns a OneToMany.
class ManyToNone {
primary: Model,
hasManySet: Set<Model>,
hasManyName: string,
belongsToName: string
}
- If the relationship already exists
- Remove
recfromhasManySet - Unlink
rec - Notify
primary[hasManyName] - Notify
rec[belongsToName]
- Add
rectohasManySet - Link
rec - Notify
primary[hasManyName] - Notify
rec[belongsToName]
class ManyToNone {
primary: Model,
hasManySet: Set<Model>,
hasManyName: string
}
- Remove
recfromhasManySet - Notify
primary[hasManyName]
struct OneToNone {
primary: Model,
belongsTo: Model,
belongsToName: string
}
A OneToNone relationship is like a OneToMany relationship without a hasMany inverse.
- If the relationship already exists:
- Update the relationship's
belongsTowith the new value
- Update the relationship's
- Otherwise:
- Create a new
OneToNonewithprimary: rec,belongsTo: value, andbelongsToName: name
- Create a new
- Null out
belongsTo - Notify
primary[belongsToName]of the change
- Notify
primary[belongsToName]of the change
class OneToOne {
a: Model,
b: Model,
aName: string,
bName: string
}
OneToOne records aren't pinned on either side.
- Assert that the relationship doesn't exist
- Create a new
OneToOnewitha: rec,b: value,aName: name,bName: <inverseName>
- Unlink both records
- Notify
a[aName]andb[bName] - (the relationship should be GCed after this)
- Notify
aandb