Cristian Boariu
Cristian Boariu

Reputation: 9621

Why I receive 'object is not a function'?

In my nodejs app, inside User mongoose schema I have this method:

/*
 * Passport-Local Mongoose will add a username, hash and salt field to store the username, the hashed password and the salt value.
 */
var User = new Schema({
  email: String,
  token: String,
  twitter: {
    id: String,
    token: String,
    displayName: String,
  }
});

    /*
 * Find user by twitter id.
 */
User.statics.findOrCreateByTwitterId = function (token, tokenSecret, profile, fn) {
  this.findOne({
    'twitter.id': profile.id
  }, function (err, user) {
    if (err) return fn(err, null);
    if (user) {
      return fn(null, user)
    };

    // create user
    var newUser = new User();
    newUser.username = profile.username;
    newUser.twitter.id = profile.id;
    newUser.token = token;
    newUser.displayName = profile.displayName;

    // create user
    newUser.save(function (err) {
      if (err) {
        return fn(null, null);
      }
      return fn(null, newUser)

    });

  });
};

User.plugin(passportLocalMongoose);

module.exports = mongoose.model('User', User);

When it is called I receive:

2015-02-24T07:47:24.162Z - debug: Mongoose:  -  users  -  findOne  -  { 'twitter.id': '90411931' } 
2015-02-24T07:47:24.327Z - error: Caught exception:  TypeError: object is not a function

where line 32 is:

var newUser = new User();

Do you see any issue?

Upvotes: 0

Views: 80

Answers (3)

JohnnyHK
JohnnyHK

Reputation: 311835

To create a new user, you need to new the model, not the User schema. So save off the initial this in the static function that's the model so it's not lost once inside the findOne callback and then use that to create the user:

User.statics.findOrCreateByTwitterId = function (token, tokenSecret, profile, fn) {
  var model = this;
  model.findOne({
    'twitter.id': profile.id
  }, function (err, user) {
    if (err) return fn(err, null);
    if (user) {
      return fn(null, user)
    };

    // create user
    var newUser = new model();
    newUser.username = profile.username;
    newUser.twitter.id = profile.id;
    newUser.token = token;
    newUser.displayName = profile.displayName;

    // create user
    newUser.save(function (err) {
      if (err) {
        return fn(null, null);
      }
      return fn(null, newUser)

    });

  });
};

Upvotes: 0

Peter Lyons
Peter Lyons

Reputation: 145994

To reference the current model from within a schema, you can do var newUser = new this.constructor();

Upvotes: 1

sarveshseri
sarveshseri

Reputation: 13985

Well... mongoose.Schema can not be instantiated. You need to create a model from the schema like this,

var UserModel = mongoose.model( 'UserModel', User );

Upvotes: 1

Related Questions