Mongoose: How to deal with circular dependencies

Created on 31 Jan 2016  路  6Comments  路  Source: Automattic/mongoose

I have two models:

// app/models/message.js
var User = require('./user');

var MessageSchema = new Schema ({
  sender: {type: Schema.Types.ObjectId, ref: 'User', required: true},
});

MessageSchema.methods.toJSON = function() {
  return {
    sender: User.publicJSON(this.sender)
  };
}

// app/models/user.js

var Message = require('./message')
var UserSchema = new Schema ({
});

UserSchema.methods.recentMessages = function() {
  return Message.where({sender: this.id});
};

UserSchema.statics.publicJSON = function(user) {
  return {
    id: this.id,
    recent_messages: user.recentMessages()
  }
};

Requiring one from the other causes problems and causes a copy of the model to be returned before it's fully formed. Specifically, before the User model has it's publicJSON static attached to it. Do you know of a way to deal with this issue?

Most helpful comment

Hard solution: use a dependency injector. Easy solution: if you create a model using mongoose.model('Message', MessageSchema); you can then access the model with mongoose.model('Message');, so all you need to do is require('mongoose'); in the file to access your models.

All 6 comments

Hard solution: use a dependency injector. Easy solution: if you create a model using mongoose.model('Message', MessageSchema); you can then access the model with mongoose.model('Message');, so all you need to do is require('mongoose'); in the file to access your models.

@vkarpov15 that 'easy' solution breaks down when you've got models being loaded one after the other which depend on each other - you get the error MongooseError: Schema hasn't been registered for model. Is there a way around this? I guess the best way would be a separation of concerns approach and use a controller or helper method to handle it.

Can you clarify what you mean by models "which depend on each other"? If you have schemas that depend on each other, then I'd recommend you keep them in the same file, but that's a quirk of node rather than a mongoose issue

Hard solution: use a dependency injector. Easy solution: if you create a model using mongoose.model('Message', MessageSchema); you can then access the model with mongoose.model('Message');, so all you need to do is require('mongoose'); in the file to access your models.

Would be great if you have a code sample demonstrating this. I tried it and got MongooseError: Schema hasn't been registered for model.

@ianpogi5 most likely you're calling mongoose.model('message') before defining your model

@ianpogi5 most likely you're calling mongoose.model('message') before defining your model

My code was the same as @ajsharp. I solved it by avoiding the situation using a third file to use the two models.

But still I don't get what you mean. Doing your suggestion yields the error @developius encountered. A code example modifying @ajsharp code would be great.

Was this page helpful?
0 / 5 - 0 ratings