i have created basic node project in which i created model folder inside model folder i have schema folder and index.js
in schema folder have all schema of my project and in index.js i write some thing like this
var s1 = require('./schema/schema1');
var s2 = require('./schema/schema2');
module.export = function(app) {
schema1= s1 ;
schema2= s2 ;
}
and in controller file i m accessing model like this
var model = require('./models/');
model.schema1.find(function(err, data) {
})
but this above code not working its give me error TypeError: Cannot read property 'find' of undefined but when i try something like this in controller
var schema1= require('../models/schema/schema1');
schema1.find(function(err,data){});
its working fine but i want 1st structure in my project i using mongoose, express, node, mongodb.
Please help i don't know what i m doing wrong
Your index.js exports a function returning nothing. Either do:
var s1 = require('./schema/schema1');
var s2 = require('./schema/schema2');
module.exports = function (app) {
return {
schema1: s1,
schema2: s2
}
}
Then require like this: var model = require('./models/')(); (notice the (), it's a function, you must call it to get the returned object).
Or, if you don't use the app parameter at all:
var s1 = require('./schema/schema1');
var s2 = require('./schema/schema2');
module.exports = {
schema1: s1,
schema2: s2
}
Then you can simply var model = require('./models/'); (no () here)).
You also had a typo on module.exports, you forgot the s.
pass your Schema to second file do something like this in first file :
var mySchema = new Schema({
// my props
});
require('./app/anotherFolder.js')(mySchema)
Related
//in app.js
var x = require("x.js");
var instanceX = new x();
require("./Weather")();
//in Weather.js
instanceX.getName();
In this case instanceX wouldn't exist when referenced from Weather.js. How do I make instanceX accessible in Weather.js?
There are a number of different ways to approach this in module design. One simple way is to just pass the variable to the weather.js constructor:
//in app.js
var x = require("x.js");
var instanceX = new x();
require("./Weather")(instanceX);
//in Weather.js
var instanceX;
module.exports = function(ix) {
instanceX = ix;
}
// then elsewhere in the module
instanceX.getName();
I refer to this as the "push" model because you're pushing things to the module that you want to share with it.
I am pretty certain there is a way to pass a variable using require.
So it would look something like this:
var model = require('model')(mongoose);
With the above line of code, I want to pass my model file my database information (mongoose), so that if I access the same model with a different database, I can pass it different database information.
However, even if the above syntax is correct, I am not sure what my model file itself would have to look like. Can anyone help me out with this?
module.exports = function (mongoose) {
// . . .
return model;
};
You can pass moongoose by argument to that file
var model = require('model')(mongoose);
Your module will look like this, you can make an object in module.exports and can attach multiple properties to that object and in the end return it from the function
module.exports = function (mongoose) {
model ={};
model.properties = {};
model.yourfunction1 = function(){};
return model;
};
I guess I can't assign anything else to module.exports in this case?
Answer to your comment is explained below
Choosing between module.exports and exports depends on you
For exports
exports.object1 = {};
exports.object2 = {};
For module.exports
module.exports = function(){
myobj={}
myobj.object1 = {};
myobj.object2 = {};
return myobj
}
Now calling it will be different
For exports it will be directly available on file variable
var file = require('./file');
console.log(file.object1);
For module.exports you will execute it like a function by appending function parenthesis so that object can be returned
var file = require('./file')();
console.log(file.myobj.object1);
I'm really confused about a variable scope issue with a file required via a path in a config file. Why does my Mongoose schema method "see" the required objects when called from within the model file but not when called from my app.js file? I'm convinced that I must be doing something obviously wrong but I can't see it.
The Node project has the following (simplified) structure:
|models
-index.js
-story.js
-post.js
-app.js
-config.js
This is config.js:
config = {};
config.test = 'test';
config.models = __dirname + '/models';
module.exports = config;
This is story.js:
var config = require('../config.js');
var models = require(config.models);
var foo = {};
foo.bar = 'baz';
var storySchema = mongoose.Schema
({
author: {type: mongoose.Schema.Types.ObjectId},
root: {type: mongoose.Schema.Types.ObjectId, default: null}
});
storySchema.methods.test = function()
{
console.log(foo.bar);
console.log(config.test);
console.log(models);
}
var Story = exports.model = mongoose.model('story', storySchema);
When I create a new Story in app.js and call its test() method, I get this output:
baz (so I know it's seeing objects in the same file)
test (so I know it's seeing variables in the config file)
{} (this "should" log my models object but it logs an empty object, why?)
When I create a new Story object within the story.js file, and run it (node ./models.story.js) the values returned are as expected (the models object is logged rather than an empty object).
Update, here are the index.js and app.js files:
index.js:
module.exports = {
post: require('./post'),
story: require('./story')
};
app.js:
var config = require('./config');
var models = require(config.models);
var story = new models.story.model();
story.test();
I believe the issue is that you've created a circular dependency. Story executes require(config.models) which requires Story again inside index.js.
Rather than storing a string and requireing it everywhere, try storing the models directly in config.models:
config.js
module.exports = {
test: 'test',
models: require(__dirname + '/models')
};
In case anyone runs into this same issue, I wanted to point to a couple resources I came across that helped me resolve the issue. As ssafejava pointed out, the problem does have to do with circular dependency (although ssafejava's solution did not entirely resolve the issue) . What worked for me was designing this dependency out of my application but there are other options if doing so is not possible. See the following issues' comments for a better explanation (in particular, see 'isaacs' comments):
https://github.com/joyent/node/issues/1490
https://github.com/joyent/node/issues/1418
'this' does not appear to refer to the instantiated budget controller object. Instead it seems to refer to the global object. Does anyone know why this is?
I've defined a budget model. Injected into the controller and I'm attempting to simply generate a random 6 char string when I hit /budgets in my app. Instead this.DEFAULT_SLUG_LENGTH is undefined and I can't figure out why.
This is a dumbed down test case illustrating the issue with 'this'. I have a similar problem when referencing the injected this.budget within another function to query the db based on the slug value.
//models/budget.js
var Schema = require('jugglingdb').Schema;
var schema = new Schema('postgres',{url:process.env.DATABASE_URL});
var Budget = schema.define('budgets',{
total: Number,
slug: String
});
module.exports = Budget;
====================
//controllers/budget.js
function BudgetController (budget) {
this.budget = budget;
};
BudgetController.prototype.DEFAULT_SLUG_LENGTH = 6;
BudgetController.prototype.generateSlug = function (req,res) {
var slug = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < this.DEFAULT_SLUG_LENGTH; i++) {
slug += possible.charAt(Math.floor(Math.random() * possible.length));
}
res.send(slug);
};
module.exports = BudgetController;
===================
//app.js
var express = require('express');
var app = express();
app.use(express.bodyParser());
// models
var Budget = require('./models/budget');
// controllers
var BudgetController = require('./controllers/budget');
var budgetCtrl = new BudgetController(Budget);
// routes
app.get('/budgets',budgetCtrl.generateSlug);
app.listen(process.env.PORT || 4730);
If I manually instantiate the model/controller in the node repl, the generateSlug method works fine. If I restructure my code so that the BudgetController is a function that returns an object {} with methods, that seems to work fine. Is there some issue with my use of prototype/new ?
express takes functions and invokes them without a preceding object, so if you want to use an object method bound to a specific this as an express route handler function, you need to bind it:
app.get('/budgets', budgetCtrl.generateSlug.bind(budgetCtrl));
I don't think I quite understand how exports work in Node.js. In a bit of sample code, I noticed the exports object used in this manner:
exports = mongoose = require('mongoose')
mongoose.connect(config.db.uri)
exports = Schema = mongoose.Schema
What is happening behind the scenes when you use exports = twice like that? Looks to me like "mongoose" should not be exported. I did this quick test:
var foo
, bar
exports = foo = 'foo'
exports = bar = 'bar'
// reports 'bar' only
console.log(exports)
and the second test does overwrite the first export.
My guess is the original author of that sample code is confused about module.exports vs exports. To use the exports object, you must add properties to it like this:
exports.size = 42;
If you re-assign the exports variable to a new object, you basically lose access to the global exports object that node.js provided for you. If you do this twice or three or N times, the effect is the same. It's useless. For example: mod_b.js
var realExports = exports;
realExports.height = 42;
var exports = {};
exports.weight = 43;
And in mod_a.js
var mod_b = require('./mod_b');
console.dir(mod_b);
Run node mod_a.js and you get:
{ height: 42 }
Notice height is there but weight is not. Now, what you can do is assign module.exports to be an object, and that is the object that will be returned when another module requires your module. So you will see things like.
var x = 10;
var y = 20;
module.exports = {x: x, y: y};
Which will do what you expect. Here's some informative articles on the details.
Node.js Module – exports vs module.exports
What is the purpose of NodeJS module.exports and how do you use it?
Mastering Node
As an extension to #Peter-Lyons answer, your example is valid, your test case is incorrect.
Exporting variables like this is not recommended, but by doing that, you are exposing this variables into a global namespace.
e.g. test0.js
'use strict';
var assert = require('assert');
var test1 = require('./test1');
assert(globalVar1 === 123);
assert(globalVar2.a === 123);
test1.js -- mind the missing 'use strict';
exports = globalVar1 = 123;
exports = globalVar2 = {a:123};
Once again, it's valid, but not recommended.
Cheers.