2

I'm trying to update a relationship between a user and user_profile. I can update the user, but I keep getting this error when I try to update the user_profile:

ERROR: Error: UserProfile.relationMappings.user: modelClass is not defined

As far as I can tell I've mimicked the example from the docs, and TypeScript example, but can anyone see why this isn't working?

I included the query, both models, and the user profile migration. The contents of the BaseModel are commented out so it is equivalent to inheriting from Model directly, and the jsonSchema is only for validation so I removed them for brevity.

UPDATE

Removing the relationshipMappings from UserProfile stops the error from occurring, but since I need the BelongsToOneRelation relationship I'm still trying. At least it seems to be narrowed down to the relationMappings on the UserProfile.

Query

const user = await User.query() // <--- Inserts the user
  .insert({ username, password });

const profile = await UserProfile.query() <--- Throws error
  .insert({ user_id: 1, first_name, last_name });

Models

import { Model, RelationMappings } from 'objection';
import { BaseModel } from './base.model';
import { UserProfile } from './user-profile.model';

export class User extends BaseModel {
  readonly id: number;
  username: string;
  password: string;
  role: string;

  static tableName = 'users';

  static jsonSchema = { ... };

  static relationMappings: RelationMappings = {
    profile: {
      relation: Model.HasOneRelation,
      modelClass: UserProfile,
      join: {
        from: 'users.id',
        to: 'user_profiles.user_id'
      }
    }
  };

}

import { Model, RelationMappings } from 'objection';
import { BaseModel } from './base.model';
import { User } from './user.model';

export class UserProfile extends BaseModel {
  readonly id: number;
  user_id: number;
  first_name: string;
  last_name: string;

  static tableName = 'user_profiles';

  static jsonSchema = { ... };

  static relationMappings: RelationMappings = {
    user: {
      relation: Model.BelongsToOneRelation,
      modelClass: User,
      join: {
        from: 'user_profiles.user_id',
        to: 'users.id'
      }
    }
  };
}

Migration

exports.up = function (knex, Promise) {
  return knex.schema
    .createTable('user_profiles', (table) => {
      table.increments('id').primary();

      table.integer('user_id')
        .unsigned()
        .notNullable();
      table.foreign('user_id')
        .references('users.id');

      table.string('first_name');
      table.string('last_name');

      table.timestamps(true, true);
    });
};
mtpultz
  • 17,267
  • 22
  • 122
  • 201

1 Answers1

8

I would say that

a) it is problem of circular dependency or/and b) there is problem with import paths

One is to use absolute file paths in modelClass instead of constructors. For example

 modelClass: __dirname + '/User'

or

modelClass: require('./User').default

look at example at: https://github.com/Vincit/objection.js/blob/master/examples/express-es7/src/models/Animal.js

DonCziken
  • 693
  • 1
  • 8
  • 13
  • Thanks for reply, modules in TypeScript can't have circular dependencies, but I did try this just in case :) Seems to be related to the relationship specifically on the UserProfile – mtpultz Oct 15 '17 at 21:46
  • yea, so I mean instead to import User in UserProfile module define modelClass as path to module :) I think that should help - here is example in TS - look modelClass of owner relationship – DonCziken Oct 15 '17 at 22:02
  • 1
    Thanks you were totally right. It's funny the error doesn't describe the issue. I'd never have figured that out based on the error. The final solution was `${__dirname}/user.model` and the same for `user-profile.model` in case anyone wants to know exactly the code that worked. – mtpultz Oct 16 '17 at 07:14