Jesús Fuentes
Jesús Fuentes

Reputation: 919

Sequelize findAll is not a function

I'm making a project with Sequelize and I'm stucked in this step. The problem is that when I try to log in and the passport-local code is executed, when it reaches the User.findAll(...) it throws that findAll is not a function.

If I make console.log(User) it shows [function].

My structure:

config.js:

//Setting up the config
var Sequelize = require('sequelize');
var sequelize = new Sequelize('rocarenav2', 'root', '123456', {
   host: "localhost",
   port: 3306,
   dialect: 'mysql'
});

module.exports = sequelize;

passport.js:

// config/passport.js

// load all the things we need
var LocalStrategy   = require('passport-local').Strategy;

// load up the user model
var User            = require('../models/nuke_users');

var crypto          = require('crypto');

function hashPasswordForNuke(password) {
    return md5password =        crypto.createHash('md5').update(password).digest('hex');
}

// expose this function to our app using module.exports
module.exports = function(passport) {

// =========================================================================
// passport session setup ==================================================
// =========================================================================
// required for persistent login sessions
// passport needs ability to serialize and unserialize users out of session

// used to serialize the user for the session
passport.serializeUser(function(user, done) {
    done(null, user.id);
});

// used to deserialize the user
passport.deserializeUser(function(id, done) {
    User.findById(id, {})
    .then(function (user) {
        done(err, user);
    })
    .catch(function (error){
        done(error);
    });
});



// =========================================================================
// LOCAL LOGIN =============================================================
// =========================================================================
// we are using named strategies since we have one for login and one for signup
// by default, if there was no name, it would just be called 'local'

passport.use('local-login', new LocalStrategy({
    // by default, local strategy uses username and password, we will override with email
    usernameField : 'email',
    passwordField : 'password',
    passReqToCallback : true // allows us to pass back the entire request to the callback
},
function(req, email, password, done) { // callback with email and password from our form
    User.findAll({
        where: {
            'user_email': email
        }
    }).then(function (user) {
        if(!user)
            return done(null, false, req.flash('loginMessage', 'No user found.')); // req.flash is the way to set flashdata using connect-flash

        // if the user is found but the password is wrong
        if ((user.user_password).localeCompare(hashPasswordForNuke(password)) === -1)
            return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.')); // create the loginMessage and save it to session as flashdata

        return done(null, user);
    })
    .catch(function (error){
        done(error);
    });

}));

};

models/index.js

'use strict';

var fs        = require('fs');
var path      = require('path');
var Sequelize = require('sequelize');
var basename  = path.basename(module.filename);
var config    = require(__dirname + '/../config/config');
var db        = {};

//Create a Sequelize connection to the database using the URL in         config/config.js
var sequelize = config;

//Load all the models
fs
  .readdirSync(__dirname)
  .filter(function(file) {
      return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
 })
.forEach(function(file) {
    var model = sequelize['import'](path.join(__dirname, file));
    db[model.name] = model;
});

Object.keys(db).forEach(function(modelName) {
   if (db[modelName].associate) {
      db[modelName].associate(db);
   }
});

//Export the db Object
db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

/models/nuke_users.js

/* jshint indent: 2 */

module.exports = function(sequelize, DataTypes) {
return sequelize.define('nuke_users', {
   user_id: {
      type: DataTypes.INTEGER(11),
      allowNull: false,
      primaryKey: true,
      autoIncrement: true
   },
   username: {
      type: DataTypes.STRING,
      allowNull: false,
      defaultValue: "",
      references: {
         model: 'reps_table',
         key: 'PostName'
      }
   },
   user_email: {
      type: DataTypes.STRING,
      allowNull: false,
      defaultValue: ""
   },
   user_avatar: {
      type: DataTypes.STRING,
      allowNull: false,
      defaultValue: ""
   },
   user_password: {
      type: DataTypes.STRING,
      allowNull: false,
      defaultValue: ""
   }
 }, {
    tableName: 'nuke_users'
 });
};

/index.js

...
var models = require('./models/');
...

So, what am I doing wrong?

Upvotes: 18

Views: 28983

Answers (3)

Yaser Odat
Yaser Odat

Reputation: 1

You need to check the models route in the collections, for example, in my case, I had read() as a method in my collections like that:

  async read(id) {
    try {
      if(id) {
        return await this.model.findOne({where: {id: id}});
      } else {
        return await this.model.findAll();
      }
    } catch (e) {
      console.error(`Error in reading data with the id: ${id}`);
    }
  }

So, findAll() wouldn't work. Instead, I used read()

Upvotes: 0

Ryan Allen
Ryan Allen

Reputation: 5911

Instead of returning the model, export it from NukeUser.js:

const NukeUser = sequelize.define('nuke_users', {
    // ...
});

module.exports = NukeUser;

Then in index.js:

const NukeUser = require('../models/NukeUser');
NukeUser.findAll() //.then() ...

Upvotes: 2

doublesharp
doublesharp

Reputation: 27687

The nuke_users module is exporting a function that, when called, returns the Model. Because you aren't calling this function, it is not returning the Model, and thus the function you are looking for does not exist.

To call this exported function you would need to pass in the sequelize instance and DataTypes, as so:

var User = require('../models/nuke_users')(sequelize, DataTypes);

In your case you are using a loader in the index.js file, and it is exporting the db object which contains the models keyed by their name.

var models = require('../models'); // loads index.js
var User = models.nuke_user;       // the model keyed by its name
User.findOne(...);                 // search the model

Upvotes: 21

Related Questions