Skip to content
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

feat(core): add support for polymorphic embeddables #2426

Merged
merged 3 commits into from
Nov 17, 2021
Merged

Conversation

B4nan
Copy link
Member

@B4nan B4nan commented Nov 16, 2021

Polymorphic embeddables allow us to define multiple classes for a single embedded property and the right one will be used based on the discriminator column, similar to how single table inheritance work.

enum AnimalType {
  CAT,
  DOG,
}

@Embeddable({ abstract: true, discriminatorColumn: 'type' })
abstract class Animal {

  @Enum(() => AnimalType)
  type!: AnimalType;

  @Property()
  name!: string;

}

@Embeddable({ discriminatorValue: AnimalType.CAT })
class Cat extends Animal {

  @Property({ nullable: true })
  canMeow?: boolean = true;

  constructor(name: string) {
    super();
    this.type = AnimalType.CAT;
    this.name = name;
  }

}

@Embeddable({ discriminatorValue: AnimalType.DOG })
class Dog extends Animal {

  @Property({ nullable: true })
  canBark?: boolean = true;

  constructor(name: string) {
    super();
    this.type = AnimalType.DOG;
    this.name = name;
  }

}

@Entity()
class Owner {

  @PrimaryKey()
  id!: number;

  @Property()
  name!: string;

  @Embedded(() => [Cat, Dog])
  pet!: Cat | Dog;

}

Closes #1165

BREAKING CHANGE:

Embeddable instances are now created via EntityFactory and they respect the
forceEntityConstructor configuration. Due to this we need to have EM instance
when assigning to embedded properties.

Using em.assign() should be preferred to get around this.

Deep assigning of child entities now works by default based on the presence of PKs in the payload.
This behaviour can be disable via updateByPrimaryKey: false in the assign options.

mergeObjects option is now enabled by default.

@codecov-commenter
Copy link

codecov-commenter commented Nov 16, 2021

Codecov Report

Merging #2426 (fd57049) into master (3fca9a6) will not change coverage.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff            @@
##            master     #2426   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          188       188           
  Lines        10640     10702   +62     
  Branches      2415      2436   +21     
=========================================
+ Hits         10640     10702   +62     
Impacted Files Coverage Δ
packages/core/src/decorators/Embedded.ts 100.00% <ø> (ø)
packages/core/src/decorators/Entity.ts 100.00% <ø> (ø)
packages/core/src/typings.ts 100.00% <ø> (ø)
packages/core/src/decorators/Embeddable.ts 100.00% <100.00%> (ø)
packages/core/src/entity/EntityAssigner.ts 100.00% <100.00%> (ø)
packages/core/src/entity/EntityFactory.ts 100.00% <100.00%> (ø)
packages/core/src/errors.ts 100.00% <100.00%> (ø)
packages/core/src/hydration/ObjectHydrator.ts 100.00% <100.00%> (ø)
packages/core/src/metadata/EntitySchema.ts 100.00% <100.00%> (ø)
packages/core/src/metadata/MetadataDiscovery.ts 100.00% <100.00%> (ø)
... and 9 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 3fca9a6...fd57049. Read the comment docs.

Polymorphic embeddables allow us to define multiple classes for a single
embedded property and the right one will be used based on the discriminator
column, similar to how single table inheritance work.

```ts
enum AnimalType {
  CAT,
  DOG,
}

@embeddable({ abstract: true, discriminatorColumn: 'type' })
abstract class Animal {

  @enum(() => AnimalType)
  type!: AnimalType;

  @Property()
  name!: string;

}

@embeddable({ discriminatorValue: AnimalType.CAT })
class Cat extends Animal {

  @Property({ nullable: true })
  canMeow?: boolean = true;

  constructor(name: string) {
    super();
    this.type = AnimalType.CAT;
    this.name = name;
  }

}

@embeddable({ discriminatorValue: AnimalType.DOG })
class Dog extends Animal {

  @Property({ nullable: true })
  canBark?: boolean = true;

  constructor(name: string) {
    super();
    this.type = AnimalType.DOG;
    this.name = name;
  }

}

@entity()
class Owner {

  @PrimaryKey()
  id!: number;

  @Property()
  name!: string;

  @Embedded(() => [Cat, Dog])
  pet!: Cat | Dog;

}
```

Closes #1165
@B4nan B4nan mentioned this pull request Nov 17, 2021
48 tasks
@B4nan B4nan merged commit 7b7c3a2 into master Nov 17, 2021
@B4nan B4nan deleted the embed-poly branch November 17, 2021 16:45
B4nan added a commit that referenced this pull request Dec 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature] Polymorphic embedded entities
2 participants