Search code examples
node.jsloopbackjsstrongloop

Updated related objects in Loopback behaving inconsisently


When updating a related object, I get two completely different behaviors from the same code. For example, a question belongs to a student. I run the code below on two separate machines.

Question.observe('after save', function (ctx, next) {

   var question = ctx.instance

   question.student(function (err, student) {
      student.updateAttributes({points: student.points - question.points})
   })

next();

})

On the first machine it works perfectly. So I thought I was done. But then when I run the same exact code on a different machine I get the following error:

  student.updateAttributes({points: student.points - question.points})
                                           ^
  TypeError: Cannot read property 'points' of null

I am using the memory connector

  "db": {
     "name": "db",
     "connector": "memory",
   }

The only thing I an think of is that I have two different versions of loopback (one with a bug and the other one without) ... but then package.json is exactly the same for both also!?

{
  "name": "foo",
  "version": "1.0.0",
  "main": "server/server.js",
  "scripts": {
    "start": "node .",
    "pretest": "jshint .",
    "test": "mocha"

  },
  "dependencies": {
    "compression": "^1.0.3",
    "cors": "^2.5.2",
    "loopback": "^2.22.0",
    "loopback-boot": "^2.6.5",
    "loopback-component-explorer": "^2.1.0",
    "loopback-datasource-juggler": "^2.39.0",
    "serve-favicon": "^2.0.1"
  },
  "devDependencies": {
    "chakram": "^1.2.1",
    "jshint": "^2.8.0",
    "loopback-testing": "^1.2.0",
    "mocha": "^2.3.4",
    "mocha-bamboo-reporter": "^1.1.0"
  },
  "repository": {
    "type": "",
    "url": ""
  },
  "description": "foo"
}

Solution

  • You are not checking for errors in question.student. So first you need to fix that.

    Then, probably not completely related, but question.student is most likely asyncronous, so you are calling next before question.student is finished.

    A better code would look like this

    Question.observe('after save', function (ctx, next) {
    
       var question = ctx.instance
    
       question.student(function (err, student) {
         if (err) return next(err);
           
         student.updateAttributes({points: student.points - question.points})
             
         next();
       });
    });

    Also, I don't know anything about updateAttributes but if it is async you also need to call next() only once it has finished (using a callback function like you did for question.student for example), and check for errors as well.

    ALWAYS check errors. It's more than just a good practice.