Accessing Mongoose schema object from Express 3 routes

How do I expose MongooseSchema objects set in app.js to the routes?

I get this error when trying to use a variable set in app.js from routes/index.js. I've been using node for just a few months, so I'm not sure what I'm missing here.

Please note I am using Express v3.3.4

500 ReferenceError: ProfileSchema is not defined

In my app.js file I have:

var express = require('express')
  , util = require('util')
  , Promise = require('bluebird')
  , crypto = require('crypto')
  , routes = require('./routes')
  , http = require('http')
  , path = require('path');

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

/*** ..... ***/

app.get('/user/home', routes.user_home);

And in my /routes/index.js I have:

exports.user_home = function(req, res){
    //foo
}

I would like to do this inside of that user_home route:

ProfileSchema.find({ users: 'joeblow' }, function (err, docs) {});

But the ReferenceError is thrown, since ProfileSchema is not accesible to the route.

NOTE: I can use ProfileSchema.find() from app.js just fine.

That's because your ProfileSchema is only defined in app.js, but app.js and /routes/index.js do not share the same scope !

This might be confusing at first, because it's different from client-side JavaScript, but you should take a few minutes to carefully read Node.js docs regarding globals. Quoting from the docs,

In browsers, the top-level scope is the global scope. That means that in browsers if you're in the global scope var something will define a global variable. In Node this is different. The top-level scope is not the global scope; var something inside a Node module will be local to that module.

To fix your issue, you have two solutions

  • You can either require your ProfileSchema directly from /routes/index.js

    var ProfileSchema = require('./models/schemas').ProfileSchema;
    
    exports.user_home = function(req, res){
        //ProfileSchema is defined ! Hurray !
    }
    
  • Or, if you still want to require ProfileSchema in app.js, you need to do something that is called dependency injection, which a complicated word for saying you need to pass your ProfileSchema variable to /routes/index.js. One way to do that is to export a function in /routes/index.js that will take ProfileSchema as a parameter. So you would need to change your code to :

    exports.user_home = function(ProfileSchema){
       return function(req, res){
        //ProfileSchema is defined ! Hurray !
      }
    }
    

    And you would pass the parameter in app.js like so :

    var ProfileSchema = require('./models/schemas').ProfileSchema;
    app.get('/user/home', routes.user_home(ProfileSchema));