当使用书架的withRelated得到“无法读取未定义的属性'toString'”

Posted

技术标签:

【中文标题】当使用书架的withRelated得到“无法读取未定义的属性\'toString\'”【英文标题】:When using bookshelf's withRelated getting "Cannot read property 'toString' of undefined"当使用书架的withRelated得到“无法读取未定义的属性'toString'” 【发布时间】:2016-05-16 10:01:18 【问题描述】:

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

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();
    )
]);

当我随后在旨在获取帖子的服务器路由中运行以下命令时:

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)

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

【问题讨论】:

【参考方案1】:

您正在使用非标准外键名称(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');
  ,
);

【讨论】:

以上是关于当使用书架的withRelated得到“无法读取未定义的属性'toString'”的主要内容,如果未能解决你的问题,请参考以下文章

为啥我在 React 中得到“无法读取未定义的属性(读取 'map')”,而没有语法错误

graphql dataloader 无法读取未定义错误的属性“加载”

在props中得到的问题是 "无法读取未定义的属性'map'" [重复] 。

从 React Context 消费返回无法读取未定义的属性“地图”

TypeError:尝试上传图像时无法读取未定义的属性“路径”

Jquery tokenInput - 无法读取未定义问题的属性