Node + Express + Bookshelf - node.js

I'm new to Node world. I want to build a Node+Express+Bookshelf (forget the front end for now). I'm following this tutorial.
But I want to refactor to what a Node structure looks like:
app/
controller/
models/
...
server.js
gruntFile.js
...
As I am still new to this world, I cannot figure out where the initialization goes,
Bookshelf.DB = Bookshelf.initialize({
client: 'postgres',
connection: {
....
}
});
And how to write my model inside the app/models/users.server.model.js would go. This is what I have:
'use strict';
var Bookshelf = require('bookshelf').DB;
exports.model = Bookshelf.Model.extend({
tableName: "users",
});
And finally, how do I use my model in some other file?

I just include the files with the model in the controller, there is this node lib that basically let you include an entire folder
include-folder

You should use Bookshelf.Registry plugin for that:
http://bookshelfjs.org/#Plugins-Registry
Then just require all your models and define them like this:
module.exports = bookshelf.model('MyModel', { ... });
To retrieve a model afterwards, do:
var MyModel = bookshelf.model('MyModel');

Related

How to pass properties into a require module?

In my index.js I require a config file for connection strings etc, like this:
var config = require('./config');
config.js then does:
module.exports = config;
so in index.js I can use the properties off config like config.db_connect_string.
When I also require for instance db.js to do the database stuff, how can I access properties of config within the functions I create in db.config and export back to index.js?
Hope this makes sense! I'm starting out with node.
I don't know what db.js looks like, but you should be able to inject the config object into the db.js module from your index.js file, and then use curried functions to create the db object you want to export.
Like so:
At index.js
var config = require('./config');
var { makeDB } = require('./db');
var db = makeDB(config)
At db.js
module.exports.makeDB =
// Pass in the expected config object
function(config) {
// If your db module needs parameters
// you can pass them in here
return function(){
// Create db module here.
// The properties of the config object
// passed in will be available here.
// Be sure to return the database object.
return db;
}
}

Express.js db module after refactoring routes

I had a simple app in node/express and after watching a course on the net, it helped me refactor the routes in my app but I found a little problem after doing so.
The problem is that my routes are using a variable called "db" that is an instance of a nedb access point.
var db = {
users: new nedb({ filename: "db/users.db", autoload: true })
};
Of course I can copy the 5 lines of code in the top of every route file to declare it but that would not be very DRY.
I tryed to put it in a separate file and export the variable:
...
module.exports = db;
And then import it in every file with:
var db = require("./db");
...
But this didn't worked as expected (The error was : Cannot find module './db')
This is a simplified structure of my files
db/
users.db
routes/
users.js
app.js
db.js
Any ideas or best practice/elegant way for solving this?
Thank you.
you need to require with a relative path. If you require inside /routes folder, you must write
var db = require("../db");

How to avoid using global?

I have very small nodejs app. Inside this application I define a model object in app.js like so:
global.model = {
name: 'Foobar'
};
The model is not persisted to any storage but kept in memory all the time. My requirement is, to be able to read and modify this model inside any module of my app.
I read that it is bad practice to use global. What is the better way? Through exports? Can you explain?
You can have a single module that creates and stores the model. Then, any other module that wants to get the model can require() your model module and then call a method on it to fetch the single shared model.
in model.js:
var mymodel = {
name: 'Foobar'
}
module.exports.getModel = function() { return mymodel;}
in any other module that wants to get the model:
var mymodel = require('./model').getModel();
If your model module would not generally be used for other things, then you could simplify it like this:
var mymodel = {
name: 'Foobar'
}
module.exports = function() { return mymodel;}
in any other module that wants to get the model:
var mymodel = require('./model')();

grunt + mochaTest: Change working directory?

I`m trying to implement testing for my nodejs-project with grunt-mocha-test and have issues with different/incorrect paths.
Like I saw it elsewhere, I want to get all dependecies by just requiring my server.js.
gruntfile.js
mochaTest: {
test: {
options: {
reporter: 'spec',
require: 'app/server.js'
},
src: ['app/test/**/*.js']
}
}
My current project structure looks like this
gruntfile.js
app/server.js
app/models/..
app/controllers/..
app/tests/..
users.controller.test.js
var userCtl = require('../controllers/users.controller');
describe("return5", function () {
it("should return 5", function () {
var result = userCtl.return5(null, null);
expect(result).toBe(5);
});
});
users.controller.js
var mongoose = require('mongoose');
var User = mongoose.model('User'); // <- Mocha crash: Schema hasn't been registered for model "User".
..
In my server.js I use:
..
// config.js: https://github.com/meanjs/mean/blob/master/config/config.js
config.getGlobbedFiles('./models/**/*.js').forEach(function (path) {
require(path); // never called with mochaTest
});
..
console.log(process.cwd()); // "C:\path\project" (missing /app)
..
So the cwd is different to what it should be.
Can someone please help me getting around this issue?
I will clarify the title as soon as I know what I`m doing wrong.
Thank you.
The confusion is due to the difference between module paths and filesystem paths.
When you do require("./blah"), the . is interpreted to mean "start with the path of the current module". Since this is relative to the module you are currently in, it will resolve to different values depending on where the module is located.
When you run process.cwd() this is returning the current working directory of the process. This does not change from module to module. It changes when your code calls process.chdir(). Also, when you perform filesystem operations that use ., this is interpreted relative to process.cwd().
So that you get C:\path\project from process.cwd() is not surprising since this is where you'd typically run Grunt (i.e. at the top level of your project). What you can do if you want paths relative to a module is use __dirname. For instance, this code reads files from a foo subdirectory in the same location where the module that contains this code is located:
var path = require("path");
var fs = require("fs");
var subdir = path.join(__dirname, "foo");
var foofiles = fs.readdirSync(subdir);

Why doesn't my Mongoose schema method "see" my required object?

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

Resources