Search code examples
javascriptnode.jses6-promisebookshelf.jsknex.js

Correct way to set up models in Node.js


I'm building a small Node/Express app and I have set up Knex with a postgresql adapter. That all works. I know it works because I can do a sql query and the results are what I want - the rows from a particular table. But I'm trying to set up models so that I can bring in related data and do validations. I'm using bookshelf for this.

I have set up my models like this:

base.js

var knex = require('../../config/db');
var bookshelf = require('bookshelf')(knex);
bookshelf.plugin('registry');

module.exports = bookshelf;

food.js

var bookshelf = require('./base');
var Meal = require('./meal');

var Food = bookshelf.Model.extend({
  tableName: 'foods',
  meal: function() {
    return this.belongsTo(Meal);
  }
});

module.exports = bookshelf.model('Food', Food);

meal.js

var bookshelf = require('./base');
var Day = require('./day');
var Food = require('./food');

var Meal = bookshelf.Model.extend({
  tableName: 'meals',
  foods: function() {
    return this.hasMany(Food);
  },
  day: function() {
    return this.belongsTo(Day);
  }
});

module.exports = bookshelf.model('Meal', Meal);

day.js

var bookshelf = require('./base');
var Meal = require('./meal');

var Day = bookshelf.Model.extend({
  tableName: 'days',
  meals: function() {
    return this.hasMany(Meal);
  }
});

module.exports = bookshelf.model('Day', Day);

The problem is that when I require the model in the router, I get a NotFoundError like this:

model: 
  { [Function]
    NotFoundError: [Function: ErrorCtor],
    NoRowsUpdatedError: [Function: ErrorCtor],
    NoRowsDeletedError: [Function: ErrorCtor] }

I'm trying to retrieve the db results like this:

var Meal = require('../models/meal');

var meals = Meal.fetchAll().then(function(collection) {
  return collection;
});
...

Why is this not returning anything? This looks like what the documentation suggests.

Where am I going wrong? I'm guessing it has to do with not setting up bookshelf right or requiring the models correctly.

Any advice?


Solution

  • One reason that this call to fetchAll is not returning anything may be because the database query is asynchronous. If you are trying to use the variable meals later on in your code, it will likely still be undefined. You should put the rest of your code that needs this collection inside the .then callback, or in a new .then callback so that it will run with access to the queried data.