Skip to content
This repository has been archived by the owner on Sep 14, 2023. It is now read-only.

References

Darko Kukovec edited this page Dec 16, 2017 · 3 revisions

The main feature of the library are the references between models. There are two types of references, and they can be defined with the refs property on the model:

Direct references

The direct reference can be used if a object contains a reference to another object over id, or it has the other object nested:

// ID
{
  firstName: 'John',
  lastName: 'Doe',
  pet: 1,
  spouse: 2,
}

// Nested
{
  firstName: 'John',
  lastName: 'Doe',
  pet: {
    name: 'Fido'
  },
  spouse: {
    firstName: 'Jane',
    lastName: 'Doe'
  }
}

The references are defined in the refs property in the format {propertyName: referencedModelType} or in this case, it would be {pet: 'pet', spouse: 'person'} - it references a pet model in the property pet, and it references a person model in the property spouse.

There is also an additional property created for every direct reference - the id property. In the case of the spouse property, it would be called spouseId;

const jane = collection.add({firstName: 'Jane', pet: {name: 'Paw'}, id: 1}, 'person');
const steve = collection.add({firstName: 'Steve', spouse: 1}, 'person');

console.log(steve.spouse.firstName); // Jane
console.log(steve.spouseId); // 1
console.log(jane.pet.name); // Paw
console.log(jane.petId); // 2

Indirect references

Indirect references are used when the object is not directly referencing the target model. However, the other model has a direct reference to our object. In the previous example, we had a Person model that had a direct reference to the Pet model. Since there is a direct reference in one direction, we can create a indirect reference in the other direction:

class Pet extends Model {}
Pet.type = 'pet';
Pet.refs = {
  owner: {
    model: 'person',
    property: 'pet',
  }
};

In this example, we define that the Pet model has a reference to all Person models that have the reference to this Pet model instance in the pet property.

Combining reference types

To make things more complicated, we can define the following direct reference:

class Person extends Model {}
Person.type = 'person';
Person.refs = {
  parents: 'person',
  spouse: 'person',
};

Keep in mind that a reference can either be a single model or an array of models. Once we have a direct reference to persons parents, we can also define the opposite reference - children:

class Person extends Model {}
Person.type = 'person';
Person.refs = {
  parents: 'person',
  spouse: 'person',
  children: {
    model: 'person',
    property: 'parents',
  }
};

This way, when we create a parents reference from one model to another, the children reference will also exist.

const steve = collection.add({firstName: 'Steve'}, 'person');
const jane = collection.add({firstName: 'Jane'}, 'person');
const bob = collection.add({firstName: 'Bob'}, 'person');
const john = collection.add({firstName: 'John'}, 'person');

steve.spouse = jane;

bob.parents = [steve, jane]; // We can expect this to be an array...
john.parents = steve; // ...or we can set it as a single model reference for now

console.log(jane.children[0].firstName); // Bob
console.log(steve.children[0].firstName); // Bob
console.log(steve.children[1].firstName); // John

Dynamic references

If you need to add an reference that is specific only to one instance of the model, you can use the assignRef method:

bob.assignRef('siblings', [john]);

Limitations

There are currently four limitations:

  1. There is no way to force a reference to be a single model or an array. Depending on the data, it will be one or the other.
  2. A indirect reference can't be set, e.g. we can't set the persons children, only the parents.
  3. A reference can only be to a single model type, e.g. a pet reference can refer to a pet model, but can't refer to the cat and dog models at the same time.
  4. There is no way to have both direct and indirect references for the same property, e.g. when we set a spouse property on the steve model, jane model won't have the spouse property automatically defined - we need to do it manually.
  5. A model (as opposed to the id reference) reference can't be set on a model if it's not in a collection.
  6. If a model has a reference and it's not in a collection or the referenced model is not in the same collection, only the reference model id can be retrieved.