Placing Backbone Models in external files using node.js - node.js

I'm trying to find my way through node.js and backbone.js. My intention is to share at least all model-states with the server and browser. Right now I'm not quite sure if I really need to share views as well. I also want to handle all routes by express and nodejs and not backbone. To keep my code a wee bit more structured I was looking forward to keep each model in a separate *.js file. By doing so I'm running into following error message:
TypeError: Object #<Object> has no method 'extend'
I thought it might be a problem with underscore missing in the separate file, so here is my basemodel:
models/BaseModel.js
var Backbone = require('../node_modules/backbone'),
_ = require('../node_modules/underscore'),
var BaseModel = Backbone.Model.extend({
modelName: 'basemodel'
});
exports.BaseModel = BaseModel;
app.js
var BaseModel = require('./models/BaseModel');
var MyModel = BaseModel.extend({
// ... attributes, functions etc.
});
Does anyone have a hint what I'm doing wrong there?

Then try this code in app.js:
BaseModel = require('./models/BaseModel').BaseModel;
Or in models/BaseModel.js not of exports.BaseModel = BaseModel; use it - module.exports = BaseModel

I actually figured it out. The flaw was in referencing to the BaseModel, so
this
var MyModel = BaseModel.extend({
//
});
had to turn into:
var MyModel = BaseModel.BaseModel.extend({
//
};
because of
exports.BaseModel = BaseModel;
in BaseModel.js

Related

Having control flow issue with mongoose model's find

I'm completely new to node and it's frameworks Koa and express. I've a mongoose model called Drawing and a router module for that.
Problem is with express routers I was able the get the data from database using Drawing.find method but with Koa, control is not even going into Drawing.find. And I'm not able to get the data at all. Please find the following related code and help me understand the things better.
This is my router module
import * as Router from "koa-router";
import Drawing from "../../models/drawing";
function getRoutesForDrawing(): Router {
console.log("Inside getRoutes for drawing");
let route = new Router();
route.get("/drawing", function(context,next) {
console.log("Inside /drawing");
Drawing.find(function(err,drawings) {
console.log("Not gettig executed");
context.body = "Welcome";
});
//context.body = "Welcome";
});
}
export default getRoutesForDrawing();
And the model is
import mongoose = require("mongoose");
export interface IDrawing extends mongoose.Document {
drawingId:Number,
drawingName:String,
updatedOn:Date,
updatedBy:Number
};
export const DrawingSchema = new mongoose.Schema({
drawingId:Number,
drawingName:String,
updatedOn:Date,
updatedBy:Number
});
const Drawing = mongoose.model<IDrawing>('Drawing', DrawingSchema);
export default Drawing;
As you can see in my router module, the control is actually coming for /drawing and it's printing in console "Inside /drawing" but then control isn't coming to Drawing.find. I'm getting difficulty in understanding this.
It's a little bit hard to figure out what's going on because it looks like you have problems all over the place. Let me point out the things that stand out:
getRoutesForDrawing is declared to return a router and doesn't return anything
Koa routes are not like express. In particular they are not callback based. They take either generator functions (Koa 1.x) or async functions (Koa 2.x). You seem to expect that it's wanting a callback function which won't work. Assuming koa 2.x, its router.get('/drawing', async(context) => {...});
Assuming koa 2.x, you need to await the result of the mongoose methods, e.g. context.body = await Drawing.find({})

Two way communication between routers within express app

I have an express app that has a router for different sections of my application, each contained within individual files. At the end of each file I export the router object like so.
var express = require("express");
var router = express.Router();
//routing handlers
module.exports = router;
However my problem is that I am trying to implement a feature were a user is allowed to edit a post that could be displayed on the front page, therefore in order to have the most current version of the user's post I need to be able to know when the user edits the post to make the necessary changes.
I have two modules one that handles dispatching the user's posts call this module B and another that handles editing call this module A. I need to be able to have module A include handler function and an array from module B, but I also need module B to be able to be notified when to make changes to the its array that module A requires.
I have tried
module A
var express = require('express');
var EventEmitter = require('events').EventEmitter;
var evt = new EventEmitter();
var router = express.Router();
var modB = require('moduleB');
router.evt = evt;
module.exports = router;
Module B
var express = require('express');
var router = express.Router();
var modA = require('moduleA').evt;
modA.on('myEvent',handler);
var myArray = [....];
router.myArray = myArray;
module.exports = router;
This gives me an undefined for modA and throws an error. I suspect it might be the order the modules are included but anyhow I would like to obtain some feedback since I sense that this might not even be good practice.
I think you are running into a common scenario for someone just starting out with express. A lot of people stick everything into routes/controllers when really the route should be very simple and just extract the data needed to figure out what the request is doing and then pass it to a service for most of the processing.
The solution is to create a Service and put the bulk of your logic and common code there, then you can wire up ModA and ModB to use the Service as needed.
EDIT with an example(not working but should give you a good starting point):
Shared Service
var EventEmitter = require('events').EventEmitter;
var evt = new EventEmitter();
module.exports = {
saveData: function(data) {
// do some saving stuff then trigger the event
evt.emit('myEvent', data);
},
onDataChange: function(handler) {
evt.on('myEvent', handler);
}
};
Module A
var service = require('SharedService.js');
// listen for events
service.onDataChange(function(e, data) {
// do something with the data
});
Module B
var service = require('SharedService.js');
// save some data which will cause Module A's listener to fire
service.saveData(data);
This example above hides the implementation of EventEmitter which may or may not be desirable. Another way you could do it would be to have SharedService extend EventEmitter, then your Modules could listen/emit directly on the service.

NodeJS (Express) - project structure and mongo connection

I started a new project from scratch with ExpressJS.
Everything works fine but now I begin to have a dozen of 'app.get(....)' function and I need to give the project a structure.
What I have in mind is quite simple, it should have a folder named 'routes' containing a file such as 'module1.js', with all of the app.get related to that module. (like I've seen in many examples)
The issue is how to tell Express to route 'http://url/module1/' to that route file and how to pass it a param variable, containing for instance the mongodb connection.
what I tried is :
var params = {
db: myMongoConnection
};
var mod1 = require('routes/module1');
app.use('/module1', mod1);
but now I still miss the 'params'.
If I try to pass it as an argument to the require method i get an error saying it needs middleware.
Another issue is related to the fact that the myMongoConnection is valid in the connection callback, so I think i need to require and use the route.js inside the MongoClient connect callback.
Any idea?
thanks a lot
For custom modules, create a folder, call it modules
In its index.js, expose the modules that you need.
Something like,
var mods = [
'mod1',
'mod2',
];
function init() {
var expose = {};
var params = {
db: myMongoConnection
};
mods.forEach(mods, function (mod) {
expose[mod] = require('./' + mod)(params);
});
return expose;
}
// export init
module.exports = init;
In mod1.js, wrap the params
module.exports = function(params) {
// all your functions here will have access to params.
}
Then in, server/app.js, require this and set it in the app.
app.set('mods', require('path-to/modules'));
Now, you can access all your modules, using app.get('mods').moduleName.methodname

Using Express.js 3 with database modules, where to init database client?

Knowing that Express.js pretty much leaves it to developer on deciding app structure, and after reading quite a few suggestions on SO (see link1 and link2 for example) as well as checking the example in official repo, I am still not sure if what I am doing is the best way forward.
Say I am using Redis extensively in my app, and that I have multiple "models" that require redis client to run query, would it be better to init redis client in the main app.js, like this:
var db = redis.createClient();
var models = require('./models')(db);
var routes = require('./controllers')(models);
or would it be better to just init redis in each model, then let each controller require models of interests?
The latter approach is what I am using, which looks less DRY. But is passing models instance around the best way? Note that I am loading multiple models/controllers here - I am not sure how to modify my setup to pass the redis client correctly to each models.
//currently in models/index.js
exports.home = require('./home.js');
exports.users = require('./user.js');
TL;DR, my questions are:
where best to init redis client in a MVC pattern app?
how to pass this redis client instance to multiple models with require('./models')(db)
Update:
I tried a different approach for index.js, use module.exports to return an object of models/controllers instead:
module.exports = function(models){
var routes = {};
routes.online = require('./home.js')(models);
routes.users = require('./user.js')(models);
return routes;
};
Seems like a better idea now?
Perhaps it's useful if I share how I recently implemented a project using Patio, a SQL ORM. A bit more background: the MVC-framework I was using was Locomotive, but that's absolutely not a requirement (Locomotive doesn't have an ORM and it leaves implementing how you handle models and databases to the developer, similar to Express).
Locomotive has a construct called 'initializers', which are just JS files which are loaded during app startup; what they do is up to the developer. In my project, one initializer configured the database.
The initializer established the actual database connection, also took care of loading all JS files in the model directory. In pseudocode:
registry = require('model_registry'); // see below
db = createDatabaseConnection();
files = fs.readDirSync(MODEL_DIRECTORY);
for each file in files:
if filename doesn't end with '.js':
continue
mod = require(path.join(MODEL_DIRECTORY, filename));
var model = mod(db);
registry.registerModel(model);
Models look like this:
// models/mymodel.js
module.exports = function(db ) {
var model = function(...) { /* model class */ };
model.modelName = 'MyModel'; // used by registry, see below
return model;
};
The model registry is a very simple module to hold all models:
module.exports = {
registerModel : function(model) {
if (! model.hasOwnProperty('modelName'))
throw Error('[model registry] models require a modelName property');
this[model.modelName] = model;
}
};
Because the model registry stores the model classes in this (which is module.exports), they can then be imported from other files where you need to access the model:
// mycontroller.js
var MyModel = require('model_registry').MyModel;
var instance = new MyModel(...);
Disclaimer: this worked for me, YMMV. Also, the code samples above don't take into account any asynchronous requirements or error handling, so the actual implementation in my case was a bit more elaborate.

Extend View class in Express on Node.js

I'd like to override the View class in the Express framework, used in Node.js. I want to augment the lookup method, but I can't see a way to do this without altering the Express and App modules. I'd favour deriving from the Express framework, but I can't figure out a neat way to do this.
Any ideas?
Thanks
It seems to me you should be able to:
var View = require('express/lib/view');
// Keep reference to original lookup method
var _lookup = View.prototype.lookup;
// Override lookup method
View.prototype.lookup = function (path) {
// Your implementation here
};
Update:
Run this as a demonstration:
var View = require('express/lib/view');
var _lookup = View.prototype.lookup;
var express = require('express');
View.prototype.lookup = function (path) {
console.log('LOOKUP!!! ' + path);
return _lookup.call(this, path);
};
var app = express();
app.get('/', function (req, res) {
res.render('foo.jade');
});
app.listen(3000);
Run
node app & sleep 1 && curl localhost:3000
I hope this will demonstrate the viability of this way of overriding a method.
It depends on which version of Express you are using.
You can easily augment the view lookup code only if your app is using Express prior to version 3
Since Express 3.0 that's not doable anymore.
You can check one of my old related answers for sample code:
Multiple View paths on Node.js + Express

Resources