Search code examples
mysqlnode.jsnode-orm2

Why is the order in the Setup so hard?


I build an node express app based off the node-orm2 example project which is included in the library. I had an nasty 'bug' where my return value looked messed up.

An "User" has only one "Permission": User.hasOne('permission', db.models.permission, {required: true, autoFetch: true}); And a "Company" has one owner but this is reversed so a "User" has multiple "Companies". Company.hasOne('user', db.models.user, { required: true, reverse: 'companies', autoFetch: true});

First setup:

function setup(db, cb) {
 require('./company')(orm, db);
 require('./user')(orm, db);
 require('./permission')(orm, db);

 return cb(null, db);
}

Messed up result:

{
  "id": 1,
  "username": "l.vanbuiten",
  "name": "Lex",
  "surname": "van Buiten",
  "age": "1992-05-13T22:00:00.000Z",
  "createdAt": "2015-12-21T23:25:04.000Z",
  "permission": {
    "id": 1,
    "username": "l.vanbuiten",
    "name": "Lex",
    "surname": "van Buiten",
    "age": "1992-05-13T22:00:00.000Z",
    "createdAt": "2015-12-21T23:25:04.000Z",
    "permission_id": 1
  },
  "companies": []
}

After swapping these setup rows things got as i wanted:

How it should be:

function setup(db, cb) {
 require('./permission')(orm, db);
 require('./user')(orm, db);
 require('./company')(orm, db);

 return cb(null, db);
}

Desired result

{
  "id": 1,
  "username": "l.vanbuiten",
  "name": "Lex",
  "surname": "van Buiten",
  "age": "1992-05-13T22:00:00.000Z",
  "createdAt": "2015-12-21T23:25:04.000Z",
  "permission": {
    "id": 1,
    "name": "permission name"
  },
  "companies": [
    {
      "id": 1,
      "name": "company name",
      "description": "company description",
      "createdAt": "2015-12-21T23:25:25.000Z"
    }
  ]
}

One example model:

var moment = require('moment');

module.exports = function (orm, db) {
var Company = db.define('company', {
    id:             {type: 'serial', key: true},
    name:           {type: 'text', required: true, unique: true},
    description:    {type: 'text', big: true},
    createdAt:  {type: 'date', required: true, time: true}
},
{
    cache: false,
    hooks: {
        beforeValidation: function () {
            this.createdAt = new Date();
        }
    },
    validations: {
        name: [
            orm.enforce.unique("Company already exist"),
            orm.enforce.ranges.length(1, undefined, "Company name cannot be empty"),
            orm.enforce.ranges.length(undefined, 50, "Company name is to long")
        ]
    },
    methods: {
        serialize: function () {
            return {
                id: this.id,
                name: this.name,
                description: this.description,
                createdAt: this.createdAt
            }
        }
    }
});
Company.hasOne('user', db.models.user, { required: true, reverse: 'companies', autoFetch: true});
};

How is it that the order differs so much?


Solution

  • (Disclaimer: I don't have a lot of node-orm2 experience)

    It seems to me that the way you're setting up associations is causing your problems.

    In your first setup, the order in which you define models and associations is as follows:

    • create the Company model
    • create the association between Company and User through db.models.user (which doesn't exist yet!)
    • create the User model
    • etc.

    Instead, I think you have to wait until all models have been defined before you can create the associations:

    function setup(db, cb) {
      // Create models.
      var Permission = require('./permission')(orm, db);
      var User       = require('./user')(orm, db);
      var Company    = require('./company')(orm, db);
    
      // Create associations.
      Company.hasOne('user', User, { required: true, reverse: 'companies', autoFetch: true});
      ...
    
      // Return.
      return cb(null, db);
    }
    

    (this also assumes that the exported function in each required model file returns the model, e.g. return Company at the end of company.js).