0

I'm setting up a new application I'm developing using the framework AdonisJS, I'm on the process of creating seeds and factories for my models in order to manually seed data to database easily. However, my models are related to one another and I'm getting errors while trying to achieve the full seeding. I already read the Adonis documentation but it's not clear to me yet.

This is an example of the schema I'm trying to implement:

example schema

Here is the same example in plain text:

+-----------+  +-----------------+  +-----------------+  +-----------------+
| Model A   |  | Model B         |  | Model C         |  | Model D         |
+----+------+  +----+------------+  +----+------------+  +----+------------+
| PK | id   |  | PK | id         |  | PK | id         |  | PK | id         |
+----+------+  +----+------------+  +----+------------+  +----+------------+
|    | name |  |    | name       |  |    | name       |  |    | name       |
+----+------+  +----+------------+  +----+------------+  +----+------------+
|    |      |  | FK | model_A_id |  | FK | model_B_id |  | FK | model_C_id |
+----+------+  +----+------------+  +----+------------+  +----+------------+

As you can see, the first model (Model A) has a relationship one to many with the second model (Model B) an so on. I already created a migration and I already related all my models like this:

class ModelA extends Model {

    modelBs() {
        return this.hasMany('App/Models/ModelB')
    }
}

class ModelB extends Model {

    modelA() {
        return this.belongsTo('App/Models/ModelA')
    }

    modelCs() {
        return this.hasMany('App/Models/ModelC')
    }
}

// And so on with classes ModelC, and ModelD...

As you can see in the code above, according to the AdonisJS documentation that must be done first in order to create a relationship while seeding. Then, I should create the factories for each model like so:

// File: database/factory.js

// Model A blueprint
Factory.blueprint('App/Models/ModelA', (faker) => {
  return {
    name: faker.sentence()
  }
})

// Model B blueprint
Factory.blueprint('App/Models/ModelB', (faker) => {
  return {
    name: faker.sentence()
  }
})

// And so on with Models C and D...

Finally, in my seeder file which is called ModelASeeder.js I create the relationship between all the models to relate them:

//File: database/seeds/ModelASeeder.js

const Factory = use('Factory')

class ModelASeeder {
  async run () {

    // I create only one Model A.
    const modelA_var = await Factory
      .model('App/Models/ModelA')
      .create()

    // Then I makeMany of Model B (4 of them).
    const modelB_var = await Factory
      .model('App/Models/ModelB')
      .makeMany(4)

    // As the documentation says, I associate them like so:

    await modelA_var.modelBs().save(modelB_var)


    // Then I want to assign Model C with the ModelBs that I associated to ModelA before, like so (I create 8 of them):

    const modelC_var = await Factory
      .model('App/Models/ModelC')
      .makeMany(8)

    // Then I try to assign ModelB to ModelC

    await modelB_var.modelCs().save(modelC_var)

    // And so on with the model D, etc, etc....

I'm facing an issue that I cannot figure it out. When I run the command adonis seed I get the following error message:

TypeError: relatedInstance.save is not a function
    at Proxy.save (/MyUser/User/my-app/node_modules/@adonisjs/lucid/src/Lucid/Relations/HasMany.js:165:28)

And at the end, it only seeds the first table (Model A table) and not the rest of them too. So I have two questions:

First of all, why am I getting that error?

Second, is this the best approach to achieve my goal of seeding my database like so?

Thank you so much for your time to answer my question, and sorry for if I made a mistake in my description, my English is not perfect.

1 Answers1

0

Try using saveMany() instead of save().

To persist multiple instances in hasMany or belongsToMany relationships you need to use saveMany().

Documentation: https://adonisjs.com/docs/4.0/relationships#_savemany

Rodrigo Gomes
  • 53
  • 1
  • 1
  • 5