如何将模型公开给应用程序和路由

时间:2015-06-19 14:22:55

标签: javascript node.js express orientdb waterline

我正在使用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模型暴露给我的应用的好方法吗?或者我错过了什么?

0 个答案:

没有答案