当使用书架的 withRelated 获取 "Cannot read property 'toString' of undefined"

When using bookshelf's withRelated getting "Cannot read property 'toString' of undefined"

我有一组书架模型,如下所示:

const User = bookshelf.Model.extend({
  tableName: 'users',
  hasTimestamps: true,
  posts: function() {
    return this.hasMany(Posts);
  },
});

const Posts = bookshelf.Model.extend({
  tableName: 'posts',
  hasTimestamps: true,
  author: function() {
    return this.belongsTo(User);
  },
});

使用 knex,我设置了这样的模式:

Promise.all([
    knex.schema.createTableIfNotExists('users', (tbl) => {
      tbl.increments('id').primary();
      tbl.string('name');
      tbl.string('username');
      tbl.string('email');
      tbl.timestamps();
    }),
    knex.schema.createTableIfNotExists('posts', (tbl) => {
      tbl.increments();
      tbl.string('title');
      tbl.string('body');
      tbl.integer('author').references('users.id');
      tbl.timestamps();
    })
]);

当我然后运行服务器路由中的以下内容旨在获取post:

app.get('/post/:id', (req,res) => {
  if(_.isUndefined(req.params.id))
    return;
  Posts
    .forge({id: req.params.id})
    .fetch({withRelated: 'author'})
    .then((post) => {
      res.send(post);
    });
});

我收到以下错误:

Unhandled rejection TypeError: Cannot read property 'toString' of undefined
    at Object.prepareValue (/Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/lib/dialects/postgres/utils.js:48:13)
    at /Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/lib/dialects/postgres/index.js:61:20
    at arrayMap (/Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/node_modules/lodash/lodash.js:595:23)
    at map (/Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/node_modules/lodash/lodash.js:8778:14)
    at Client.prepBindings (/Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/lib/dialects/postgres/index.js:60:28)
    at QueryCompiler_PG.toSQL (/Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/lib/query/compiler.js:49:37)
    at QueryBuilder.toSQL (/Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/lib/query/builder.js:40:44)
    at /Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/lib/runner.js:34:32
    at tryCatcher (/Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/node_modules/bluebird/js/release/util.js:16:23)
    at /Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/node_modules/bluebird/js/release/using.js:184:26
    at tryCatcher (/Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/node_modules/bluebird/js/release/promise.js:502:31)
    at Promise._settlePromise (/Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/node_modules/bluebird/js/release/promise.js:559:18)
    at Promise._settlePromise0 (/Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/node_modules/bluebird/js/release/promise.js:604:10)
    at Promise._settlePromises (/Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/node_modules/bluebird/js/release/promise.js:683:18)
    at Promise._fulfill (/Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/node_modules/bluebird/js/release/promise.js:628:18)
    at PromiseArray._resolve (/Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/node_modules/bluebird/js/release/promise_array.js:125:19)
    at PromiseArray._promiseFulfilled (/Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/node_modules/bluebird/js/release/promise_array.js:143:14)
    at Promise._settlePromise (/Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/node_modules/bluebird/js/release/promise.js:564:26)
    at Promise._settlePromise0 (/Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/node_modules/bluebird/js/release/promise.js:604:10)
    at Promise._settlePromises (/Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/node_modules/bluebird/js/release/promise.js:683:18)
    at Async._drainQueue (/Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/node_modules/bluebird/js/release/async.js:138:16)
    at Async._drainQueues (/Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/node_modules/bluebird/js/release/async.js:148:10)
    at Immediate.Async.drainQueues [as _onImmediate] (/Users/ethan/Flatiron/node/unit4/node-js-intro-to-bookshelf/node_modules/knex/node_modules/bluebird/js/release/async.js:17:14)
    at tryOnImmediate (timers.js:534:15)
    at processImmediate [as _immediateCallback] (timers.js:514:5)

有人知道这里发生了什么吗?

您使用的是非标准外键名称(author 而不是 author_id -- 请参阅 http://bookshelfjs.org/#Model-instance-belongsTo)。所以你的模型关系应该固定为:

const User = bookshelf.Model.extend({
  tableName: 'users',
  hasTimestamps: true,
  posts: function() {
    return this.hasMany(Posts, 'author');
  },
});

const Posts = bookshelf.Model.extend({
  tableName: 'posts',
  hasTimestamps: true,
  author: function() {
    return this.belongsTo(User, 'author');
  },
});