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

[Docs] Specify how to link a created entity to another #139

Open
johannchopin opened this issue Jul 2, 2021 · 5 comments
Open

[Docs] Specify how to link a created entity to another #139

johannchopin opened this issue Jul 2, 2021 · 5 comments

Comments

@johannchopin
Copy link

I have 2 factories for 2 entities Customer and Event:

Entitites

// entity/Customer.ts
import { Entity, PrimaryGeneratedColumn, Column, OneToOne, ManyToMany, JoinTable, JoinColumn } from 'typeorm'
import { Event } from './Event'

@Entity()
export class Customer {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  firstname: string;

  @Column()
  lastname: string;

  @Column()
  email: string

  @ManyToMany(() => Event, event => event.customers, { cascade: true })
  @JoinTable()
  events: Promise<Event[]>
}


// entity/Event.ts
import { Entity, PrimaryColumn, Column, CreateDateColumn, OneToMany, ManyToMany, JoinTable, DeleteDateColumn } from 'typeorm'
import { Course } from './Course'
import { Customer } from './Customer'

@Entity()
export class Event {
  @PrimaryColumn()
  id: string;

  @Column()
  name: string;

  @ManyToMany(() => Customer, customer => customer.events)
  @JoinTable()
  customers: Promise<Customer[]>
}

Factories

// factory/event.ts
import { define, factory } from 'typeorm-seeding'

import { Event } from '../../entity/Event'

define(Event, (faker) => {
  const event = new Event()

  event.id = faker.company.bsBuzz()
  event.name = faker.company.catchPhraseNoun()
  event.date = faker.date.recent()

  return event
})


// factory/customer.ts
import { Customer } from '../../entity/Customer'

define(Customer, (faker) => {
  const customer = new Customer()

  customer.firstname = faker.name.firstName()
  customer.lastname = faker.name.lastName()
  customer.email = faker.internet.email()

  return customer
})

As you can see a Customer can have multiple Events and different Customers can participate to the same Event. So my goal for the seeding part is to create 10 different Events and then create 100 Customers that participate at some of these Events. So I created 2 seeding files:

// seed/create-events.ts
import { Factory, Seeder } from 'typeorm-seeding'
import { Event } from '../entity/Event'

export default class CreateEvents implements Seeder {
  public async run(factory: Factory): Promise<any> {
    await factory(Event)().createMany(10)
  }
}


// seed/create-customers.ts
import { Factory, Seeder } from 'typeorm-seeding'
import { Customer } from '../entity/Customer'

export default class CreateCustomers implements Seeder {
  // eslint-disable-next-line class-methods-use-this
  public async run(factory: Factory): Promise<any> {
    await factory(Customer)().createMany(100)
  }
}

However that only create some entries but doesn't link them together.

I know that I could use the Event's factory inside of the the Customer's one:

// factory/customer.ts
import { Customer } from '../../entity/Customer'

define(Customer, (faker) => {
  const customer = new Customer()

  customer.firstname = faker.name.firstName()
  customer.lastname = faker.name.lastName()
  customer.email = faker.internet.email()

  customer.events = factory(Event)().createMany(10)

  return customer
})

But that will just create 10 different Events for each Customer.

So how to seed my Customers in a way that they are linked to some Events created during the seed:run command? I hope there is a way to do that and if yes I will be pleased to add it to the README documentation section.

@joaomantovani
Copy link

Hey @johannchopin, did you find how to resolve this issue?

@johannchopin
Copy link
Author

Sadly no @joaomantovani 😓 I hope to hear soon from the core maintainers that seems a bit shy 😅

@michaelpwilson
Copy link

michaelpwilson commented Sep 21, 2021

I'm not 100% on your use case and I haven't tested this, but hopefully points you in the right direction.

Use the ORM connection in the Seed file to find Customers you want the Event to have, then pass that through to the Factory:

// seed/create-events.ts
import { Factory, Seeder } from 'typeorm-seeding'
import { Customer } from '../../entity/Customer'
import { Connection } from 'typeorm'
import { Event } from '../entity/Event'

export default class CreateEvents implements Seeder {
  public async run(factory: Factory, connection: Connection): Promise<any> {
    const repository = connection.getRepository(Team);
    const customers = await repository.find();
    await factory(Event)(customers).createMany(10)
  }
}

Then add that to the Column you require:

// factory/event.ts
import { define, factory } from 'typeorm-seeding'
import { Customer } from '../../entity/Customer'
import { Event } from '../../entity/Event'

define(Event, (faker, customers: Customer[]) => {
  const event = new Event()

  event.id = faker.company.bsBuzz()
  event.name = faker.company.catchPhraseNoun()
  event.date = faker.date.recent()
  event.customers = customers
  return event
})

The problem I am currently facing is that the execution of the Seeders is done in alphabetical order. So In your case you would need to setup the relationship in Event rather than Customer.

Hope this helps.

@phamhuyhoang95
Copy link

I'm not 100% on your use case and I haven't tested this, but hopefully points you in the right direction.

Use the ORM connection in the Seed file to find Customers you want the Event to have, then pass that through to the Factory:

// seed/create-events.ts
import { Factory, Seeder } from 'typeorm-seeding'
import { Customer } from '../../entity/Customer'
import { Connection } from 'typeorm'
import { Event } from '../entity/Event'

export default class CreateEvents implements Seeder {
  public async run(factory: Factory, connection: Connection): Promise<any> {
    const repository = connection.getRepository(Team);
    const customers = await repository.find();
    await factory(Event)(customers).createMany(10)
  }
}

Then add that to the Column you require:

// factory/event.ts
import { define, factory } from 'typeorm-seeding'
import { Customer } from '../../entity/Customer'
import { Event } from '../../entity/Event'

define(Event, (faker, customers: Customer[]) => {
  const event = new Event()

  event.id = faker.company.bsBuzz()
  event.name = faker.company.catchPhraseNoun()
  event.date = faker.date.recent()
  event.customers = customers
  return event
})

The problem I am currently facing is that the execution of the Seeders is done in alphabetical order. So In your case you would need to setup the relationship in Event rather than Customer.

Hope this helps.

@michaelpwilson How you resolve order runing for each seeder ? I want my seeder file run from top to end.

@johannchopin
Copy link
Author

@michaelpwilson @phamhuyhoang95 You can easily modify the seeder order by adding a number before the filename like:

1-create-customers.ts
2-create-events.ts

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

No branches or pull requests

4 participants