3

node +expressを使用して単純なRESTAPIを作成し、ルーティングロジックをdbロジックから分離しようとしています。ルートからDBにアクセスするのに問題があります。

これが私のserver.jsコードです:

var express = require('express')
  , path = require('path')
  , http = require('http')
  , mongo = require('mongodb');

// Configure Express app
var app = express();
app.configure(function () {
    app.set('port', process.env.PORT || 3000);
    app.use(express.logger('dev'));  /* 'default', 'short', 'tiny', 'dev' */
    app.use(express.bodyParser()),
    app.use(express.static(path.join(__dirname, 'public')));
});

// Configure DB
var Server = mongo.Server
  , Db = mongo.Db
  , BSON = mongo.BSONPure
  , server = new Server('localhost', 27017, {auto_reconnect: true})
  , db = new Db('mydb', server, {safe: true});

// Open DB to see if we need to populate with data
db.open(function(err, db) {
  if(!err) {
    console.log("Connected to 'mydb' database");
    var Post = require('./routes/posts')
      , post = new Post(db);

    // Set the routes
    app.get('/:org/posts', post.find);
    app.get('/:org/posts/:id', post.get);
    app.post('/:org/posts', post.add);
    app.put('/:org/posts/:id', post.update);
    app.delete('/:org/posts/:id', post.remove);

    // Fire up the server
    http.createServer(app).listen(app.get('port'), function () {
      console.log("Express server listening on port " + app.get('port'));
    });
  }
});

post.jsファイルのロジックは次のとおりです。

var Post = function(db) {
  this.db = db;
};

Post.prototype.get = function(req, res) {
  var id = req.params.id;
  var org = req.params.org;
  var db = this.db;

  console.log('Retrieving post: ' + id + ' from org: ' + org);
  db.collection('ads', function(err, collection) {
    collection.findOne({'_id':new BSON.ObjectID(id), 'org':org}, function(err, item) {
      res.send(item);
    });
  });
};

Post.prototype.find = function(req, res) {
  var org = req.params.org;
  var db = this.db;

  console.log('Finding posts for org: ' + org);
  db.collection('posts', function(err, collection) {
    collection.find({'org':org}).toArray(function(err, items) {
      res.send(items);
    });
  });
};

Post.prototype.add = function(req, res) {
  var org = req.params.org;
  var post = req.body;
  var db = this.db;

  console.log('Adding post: ' + JSON.stringify(post) + ' for org: ' + org);
  db.collection('posts', function(err, collection) {
    collection.insert(post, {safe:true}, function(err, result) {
      if (err) {
        res.send({'error':'An error has occurred'});
      } else {
        console.log('Success: ' + JSON.stringify(result[0]));
        res.send(result[0]);
      }
    });
  });
};

Post.prototype.update = function(req, res) {
  var id = req.params.id;
  var org = req.params.org;
  var post = req.body;
  var db = this.db;

  delete post._id;
  console.log('Updating post: ' + id + ', org: ' + org);
  console.log(JSON.stringify(post));
  db.collection('posts', function(err, collection) {
    collection.update({'_id':new BSON.ObjectID(id)}, post, {safe:true}, function(err, result) {
      if (err) {
        console.log('Error updating post: ' + err);
        res.send({'error':'An error has occurred'});
      } else {
        console.log('' + result + ' document(s) updated');
        res.send(post);
      }
    });
  });
};

Post.prototype.remove = function(req, res) {
  var id = req.params.id;
  var org = req.params.org;
  var db = this.db;

  console.log('Deleting post: ' + id + ', org: ' + org);
  db.collection('posts', function(err, collection) {
    collection.remove({'_id':new BSON.ObjectID(id), 'org':org}, {safe:true}, function(err, result) {
      if (err) {
        res.send({'error':'An error has occurred - ' + err});
      } else {
        console.log('' + result + ' document(s) deleted');
        res.send(req.body);
      }
    });
  });
};

module.exports = Post;

postオブジェクトは、ルートから呼び出されたときに使用するためにdb参照を保持すると思いますが、次のエラーが発生します。

TypeError: Cannot call method 'collection' of undefined
    at Post.find (../routes/posts.js:23:6)

誰かが私を正しい方向に向けることができますか?どうもありがとう

4

2 に答える 2

7

この方法を試してください。しばらく前にStackOverflowでこれを見つけて以来、これは私のお気に入りのモジュール作成方法になりました。

server.js:

...    
var Post = require('./routes/posts')(db);
...

posts.js:

...
module.exports =function(db) {
        var module = {};

         module.get = function(req, res){
            ...
            /* db should be accessible here */

         }

         return module;
}
于 2014-05-10T17:34:02.500 に答える
1

登録しているExpressルートハンドラーによって呼び出されると、オブジェクトはメソッド内postのとして失われthisます。Expressによってどのように呼び出されても、インスタンスのメソッドがあなたのになるようにPostする必要があります。このような:bindpostthispost

// Set the routes
app.get('/:org/posts', post.find.bind(post));
app.get('/:org/posts/:id', post.get.bind(post));
app.post('/:org/posts', post.add.bind(post));
app.put('/:org/posts/:id', post.update.bind(post));
app.delete('/:org/posts/:id', post.remove.bind(post));
于 2013-01-04T00:58:43.587 に答える