我正在使用Waterline作为我的ORM和Express。我想知道暴露我的模型最好的方法是什么,所以我可以在我的应用程序中使用它们。到目前为止,我必须致电req.app.models.model_name
,这似乎有点复杂。这个代码示例有效,但我不太确定这是不是很好的做法,因为我对Node.js / Waterline和Express都很陌生。
我的文件夹结构是由express生成器进行的一些修改:
├── app.js
├── bin
│ └── www
├── models
│ ├── index.js
│ └── links.js
├── package.json
├── public
│ ├── images
│ ├── javascripts
│ └── stylesheets
│ └── style.css
├── routes
│ ├── index.js
│ └── users.js
└── views
├── error.jade
├── index.jade
└── layout.jade
这就是我在模型中使用Waterline的方法。我有一个index.js来设置Waterline并自动加载文件夹./models
// ./models/index.js
var orientAdapter = require('sails-orientdb');
var Waterline = require('waterline');
var orm = new Waterline();
var config = {
// Setup Adapters
// Creates named adapters that have have been required
adapters: {
'default': orientAdapter,
orient: orientAdapter,
},
// Build Connections Config
// Setup connections using the named adapter configs
connections: {
myLocalOrient: {
adapter: 'orient',
host: 'localhost',
port: 2424,
user: 'root',
password: 'password',
database: 'database'
}
},
defaults: {
migrate: 'alter'
}
};
// Include all files in ./models directory
var fs = require('fs');
var path = require("path");
fs
.readdirSync(__dirname)
.filter(function(file) {
return (file.indexOf(".") !== 0) && (file !== "index.js");
})
.forEach(function(file) {
var model = require(path.join(__dirname, file));
orm.loadCollection(model);
});
module.exports = {waterline: orm, config: config};
示例模型(Link
):
// ./models/link.js
var Waterline = require('Waterline');
var orientAdapter = require('sails-orientdb');
var Link = Waterline.Collection.extend({
identity: 'link',
connection: 'myLocalOrient',
attributes: {
title: {
type: 'string',
required: true
},
url: {
type: 'string',
required: true
}
}
});
module.exports = Link;
要将其挂钩到我的应用中,我修改了用于启动应用的./bin/www
node ./bin/www
)
// ./bin/www
#!/usr/bin/env node
/**
* Module dependencies.
*/
var app = require('../app');
var debug = require('debug')('v2:server');
var http = require('http');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
// START SERVER STARTUP WITH WATERLINE
var models = require('../models');
models.waterline.initialize(models.config, function(err, models) {
if(err) throw err;
// console.log(models.collections);
app.models = models.collections;
app.connections = models.connections;
// Start Server
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
});
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
我现在可以在我的路线中使用这些模型:
// ./routes/index.js
var express = require('express');
var router = express.Router();
var app = require('../app');
// Index
router.get('/links', function(req, res, next) {
req.app.models.link.find().limit(10).then(function(links) {
res.json(links);
});
});
// Create
router.post('/links', function(req, res, next) {
var link = req.app.models.link.create(req.body)
.then(function(link) {
res.json(link);
})
.catch(console.error);
});
module.exports = router;
请注意使用req.app.models.link.find()...
。
当我尝试挂钩Passport并创建文件./config/passport.js
时,我开始担心它。在第一次实现时,我得到了错误ReferenceError: req is not defined
所以我不得不更改它并将请求对象传递给我的护照策略。像这样:
// ./routes/index.js
// ...
// Login User
router.post('/login', function(req, res, next){
if(!req.body.username || !req.body.password){
return res.status(400).json({message: 'Please fill out all fields'});
}
passport.authenticate('local', function(err, user, info){
if(err){ return next(err); }
if(user){
return res.json({token: user.generateJWT()});
} else {
return res.status(401).json(info);
}
})(req, res, next);
});
我的护照本地策略:
// ./config/passport.js
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy({
passReqToCallback : true
},
function(req, username, password, done) {
// check in orientdb if a user with username exists or not
req.app.models.user.findOne({ 'username' : username },
function(err, user) {
// In case of any error, return using the done method
if (err) return done(err);
// Username does not exist, log error & redirect back
if (!user){
console.log('User Not Found with username '+username);
return done(null, false, { message: 'User Not Found with username '+username });
}
// User exists but wrong password, log the error
if (!user.verifyPassword(password)){
console.log('Invalid Password');
return done(null, false, { message: 'Invalid Password'});
}
// User and password both match, return user from
// done method which will be treated like success
return done(null, user);
}
);
}));
也许这很好,但我想知道是否有更好的方法来做到这一点。
问题:这是将我的Waterline模型暴露给我的应用的好方法吗?或者我错过了什么?