Reputation: 5510
I've got a set of Bookshelf models that looks like this:
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);
},
});
Using knex, I setup the schema like so:
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();
})
]);
When I then run the following in a server route designed to fetch a 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);
});
});
I get the following error:
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)
Does anyone know what's going on here?
Upvotes: 2
Views: 960
Reputation: 7815
You are using a non-standard foreign key name (author
instead of author_id
-- see http://bookshelfjs.org/#Model-instance-belongsTo). So your models' relations should be fixed to:
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');
},
});
Upvotes: 2