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

Need an example in the documentation of how to work with inherited entities #260

Open
KCH0000 opened this issue May 16, 2024 · 2 comments
Open
Labels
documentation Improvements or additions to documentation

Comments

@KCH0000
Copy link

KCH0000 commented May 16, 2024

📚 Documentation

We need an example in the documentation of how to work with inherited entities.

There are two Entities in the same table.
How do I make FilterableUnpagedRelation with a common DTO?

registerEnumType(ContactType, {
  name: 'ContactType',
});

@Entity('person_contact')
@TableInheritance({ column: { type: 'varchar', name: 'type' } })
export class ContactEntity {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @ManyToOne(() => PersonEntity, (person) => person.id)
  @JoinColumn({ name: 'owner_id' })
  ownerId: PersonEntity;

  @Column({ type: 'text', nullable: true })
  description: string;

  type: ContactType;
  email: string;
  phone: string;
}
@ChildEntity(ContactType.email)
export class EmailContactEntity extends ContactEntity {
  @Column({
    nullable: false,
    type: 'varchar',
    length: 255,
  })
  @IsEmail()
  @Index({ unique: true })
  email: string;
}
@ChildEntity(ContactType.phone)
export class PhoneContactEntity extends ContactEntity {
  @Column({
    nullable: false,
    type: 'varchar',
    length: 25,
    comment: '(DC2Type:phone_number)',
  })
  @IsPhoneNumber('RU')
  @Index({ unique: true })
  phone: string;
}

I need to transform PhoneContactEntity EmailContactEntity to
ContactDTO where value is either a phone number or an email.

@ObjectType('contact')
export class ContactDTO {
  @Field(() => ID)
  id: string;

  @FilterableField(() => ContactType, { nullable: false })
  type: ContactType;

  @FilterableField()
  value: string;

  @Field({ nullable: true })
  description: string;
}

I'm trying to do it through assemblers, but how use two assemblers for one DTO
Or choose a way to store data in different tables?

@KCH0000 KCH0000 added the documentation Improvements or additions to documentation label May 16, 2024
@KCH0000 KCH0000 changed the title Need Need an example in the documentation of how to work with inherited entities May 16, 2024
@TriPSs
Copy link
Owner

TriPSs commented May 17, 2024

Could you not just create resolver etc for ContactDTO and add a @ResolveField for value that returns one of the two?

We do something similiar for the Creator type, which is just a UserEntity in the database:

import { Parent, ResolveField, Resolver } from '@nestjs/graphql'
import { UserType } from '@constants/user'
import { UserEntity } from '@database/main/user.entity'

import { Creator, CreatorType } from './creator.type'

@Resolver(() => Creator)
export class CreatorResolver {

  @ResolveField()
  public name(@Parent() creator: UserEntity): string {
    if (this.isSpecialUser(creator)) {
      return creator.fullName
    }

    return creator.firstName
  }

  @ResolveField()
  public type(@Parent() creator: UserEntity): string {
    if (this.isSpecialUser(creator)) {
      switch (creator.type) {
        case UserType.API:
          return CreatorType.API

        case UserType.System:
          return CreatorType.System

        case UserType.Integration:
          return CreatorType.Integration
      }
    }

    return CreatorType.User
  }

  private isSpecialUser(creator: UserEntity) {
    return [UserType.API, UserType.Integration, UserType.System].includes(creator.type as UserType)
  }

}

@KCH0000
Copy link
Author

KCH0000 commented May 18, 2024

This is not exactly the pattern. When we use ChildEntity, we create our own Entity and DTO for each Child.
Resolver should convert ChildEntity to ContactDTO based on the type. ContactEntity is abstract.
I wrote such a Resolver, but automatic filtering in the scheme does not work on it

User {
name: String!
contacts: [ContactDTO]
}

I realized that this is not an easy solution, so for now I keep all types of contacts in one column and additionally verify before saving

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

2 participants