Skip to content

DefiningModelRelationships

Mihael Safaric edited this page May 19, 2023 · 3 revisions

Specifying one-to-one relationships

  • one-to-one relationships are specified using HasOne decorator
  • there are two ways of defining such relationships:
    • by using type
    • by providing propertyClass in HasOne decorator:
      • by providing a class (the class must extend SimpleHalModel or HalModel)
      • by providing a function that return a class

Examples

In the example below, the Car model has a relationship to the User model. The ngx-hal library determines what class to used based on the type of the owner property.

@ModelConfig(...)
export class Car extends HalModel {
  @HasOne()
  owner: User;
}

The same thing can be achieved by providing a specific class in the HasOne decorator:

@ModelConfig(...)
export class Car extends HalModel {
  @HasOne({
    propertyClass: CustomUserClass
  })
  owner: User;
}

In this case, the type of the owner property (User in this case) won't be used to dermine what class has to be used when creating an owner, but instead, the value of propertyClass will be used (CustomUserClass in this case). CustomUserClass must extend either SimpleHalModel or HalModel:

class CustomUserClass extends SimpleHalModel {}

or

class CustomUserClass extends HalModel {}

To avoid extending CustomUserClass, a function that returns CustomUserClass could be used:

class CustomUserClass {}

@ModelConfig(...)
export class Car extends HalModel {
  @HasOne({
    propertyClass: () => CustomUserClass
  })
  owner: User;
}

Circular dependencies

There might be a case where two models point to each other.

@ModelConfig(...)
export class Car extends HalModel {
  @HasOne()
  owner: User;
}

@ModelConfig(...)
export class User extends HalModel {
  @HasOne()
  favouriteOwnedCar: Car;
}

This might lead to runtime errors while accessing classes before their initialization. To avoid that, a special way of defining relationships could be used (Note: this is available from ngx-hal@3):

  1. specify modelType on one of the models (see Car model)
    • modelType is a unique string that represents that class (case sensitive)
  2. provide that string as a relationship identifier in the other model (see User.favouriteOwnedCar below)
  3. register the model by adding it in the DatastoreService.modelTypes array
@ModelConfig(...)
export class Car extends HalModel {
  public static modelType = 'car-model-unique-string';

  @HasOne()
  owner: User;
}

@ModelConfig(...)
export class User extends HalModel {
  @HasOne({
    propertyClass: 'car-model-unique-string'
  })
  favouriteOwnedCar: Car;
}

@DatastoreConfig(...)
export class HalDatastoreService extends DatastoreService {
	public modelTypes = [Car];
  ...
}