bezzoon
bezzoon

Reputation: 2019

mongoose - nodejs - has no method for some reason

Having some issues!

The error is

local: 
  { password: '$2a$08$kSflSzcciqWN78nfqAu/4.ZBZaXkqb19bEypeWcuSxg89yPNuijYO',
    email: '***@gmail.com' } } has no method 'usersCharacters'

But it does have the method! I am not sure it is being exported properly. As far as I can tell I am doing it similarly to the other methods users have except here it doesn't seem to work.

user.js model file

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

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


/* method works :D ! -- not sure if over complicated though! */
UserSchema.methods.usersCharacters = function(email,cb){
  User.findOne( {'local.email' : email }).exec(function(err, user){
    if (err) console.log("shit");
    var _return = [];

    user.characters.forEach(function(err, i){
      Character.findOne({ "_id" :user.characters[i] }).exec(function(err2, dude){
        _return.push(dude);

        /* Can't think of a smarter way to return :( */
        if ( i == user.characters.length-1)
          cb(_return);
      });
    });
  });
};

routes.js

/* This doesn't work! I am wondering how I might be able to return this users characters -- 
 *
 * The error is here btw! TypeError: Cannot call method 'usersCharacters' of undefined -- line with character : ****
 */
app.get('/profile', isLoggedIn, function(req, res) {
    var mongoose = require('mongoose');
    var UserSchema = mongoose.model('User', UserSchema);
    console.log(UserSchema);
    // ERROR ON THIS LINE! : (
    characters : req.user.usersCharacters(req.user.email, function(_characters){ 
                   console.log("list of characters: " + _characters);
                   return _characters;
                   res.render('profile.ejs', {
                     user : req.user, // get the user out of session and pass to template
                     characters : characters
                   });

here is a gist with more of my model file code:

https://gist.github.com/hassanshaikley/d4766251ec53feec8e84

Upvotes: 0

Views: 417

Answers (2)

Cameron Hudson
Cameron Hudson

Reputation: 3929

JohnnyHK is correct that the order of creating a Mongoose model object is:

  1. Create the schema properties using var UserSchema = new mongoose.Schema({...});.
  2. Add additional functions to the schema using UserSchema.methods.usersCharacters = ..., as you have done.
  3. Use the schema to create the model, as in var User = mongoose.model('User', UserSchema);
  4. Export the model using module.exports = User;

However, that is not the immediate cause of your issue. You are calling .usersCharacters() on an object called user. While it may have key-value pairs identical to those of a Mongoose document object, it is not a Mongoose document object. Instead, it is a generic Javascript object. You must first look up the corresponding Mongoose document object in your database, using the following:

User.findOne( {'local.email' : req.user.email } )).exec(function(err, userDoc){
  if (err) console.log("shit");
  var characters = req.user.usersCharacters(req.user.email, function(_characters){ 
      console.log("list of characters: " + _characters);
      return _characters;
  });
  res.render('profile.ejs', {
    user : req.user, // get the user out of session and pass to template
    characters : characters
  });
});

Note that the req.user object passed to res.render() will only contain the properties sent in the request, which may be different from those in the userDoc object.

Do be aware, however, that I am currently having trouble accessing instance methods of documents returned from using .findOne(). If you run into that problem, you can check out my thread here: Instance methods not defined for Mongoose findOne() query result?

Upvotes: 0

JohnnyHK
JohnnyHK

Reputation: 311865

Methods that you add to UserSchema after creating the User model from it, won't be available on User model instances.

So create the method before creating the User model:

UserSchema.methods.usersCharacters = function(email,cb){ ... };

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

On a related note, only the first call to mongoose.model('User', UserSchema) processes the schema to create the 'User' model. Subsequent calls ignore the UserSchema parameter and return the existing model.

Upvotes: 1

Related Questions