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 ManyArray
s and belongsTo
computed property caches.
Parameters: name
, newRecord
- let rel be
record.relationshipFor(name)
rel.removeMember(record)
- If
newValue
exists:- 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
inverse
is 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
name
relationship onrecord
- let inverseKind, inverseName be the kind and name of the inverse of the
name
relationship - 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
rec
fromhasManySet
- Unlink
rec
- Notify
primary[hasManyName]
- Notify
rec[belongsToName]
- Add
rec
tohasManySet
- Link
rec
- Notify
primary[hasManyName]
- Notify
rec[belongsToName]
class ManyToNone {
primary: Model,
hasManySet: Set<Model>,
hasManyName: string
}
- Remove
rec
fromhasManySet
- 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
belongsTo
with the new value
- Update the relationship's
- Otherwise:
- Create a new
OneToNone
withprimary: 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
OneToOne
witha: rec
,b: value
,aName: name
,bName: <inverseName>
- Unlink both records
- Notify
a[aName]
andb[bName]
- (the relationship should be GCed after this)
- Notify
a
andb