5

sailsjs 0.11, node 0.12.4. with passport 0.2.1 and passport-local 1.0

Using the sailsjs blueprint routes just to see what's going on. The project is just a simple blog, and I tried looking at a user profile in the blueprint route /user/4 to show me userid 4. This message was the result.

Any ideas what caused this?

Note: i haven't been anywhere near sails/waterline source.

Full error message

/home/vagrant/nodeprojs/<project>/node_modules/sails/node_modules/waterline/lib/waterline/model/lib/defaultMethods/toObject.js:59
    throw err;
          ^
Error: There was an error turning the model into an object.
    at new module.exports (/home/vagrant/nodeprojs/<project>/node_modules/sails/node_modules/waterline/lib/waterline/model/lib/defaultMethods/toObject.js:56:15)
    at prototypeFns.toObject (/home/vagrant/nodeprojs/<project>/node_modules/sails/node_modules/waterline/lib/waterline/model/index.js:30:14)
    at prototypeFns.toJSON (/home/vagrant/nodeprojs/<project>/node_modules/sails/node_modules/waterline/lib/waterline/model/index.js:112:20)
    at Object.stringify (native)
    at ServerResponse.res.json (/home/vagrant/nodeprojs/<project>/node_modules/sails/node_modules/express/lib/response.js:217:19)
    at sendJSON (/home/vagrant/nodeprojs/<project>/api/responses/ok.js:34:23)
    at viewReady (/home/vagrant/nodeprojs/<project>/api/responses/ok.js:72:25)
    at viewFailedToRender (/home/vagrant/nodeprojs/<project>/node_modules/sails/lib/hooks/views/res.view.js:276:16)
    at Function.app.render (/home/vagrant/nodeprojs/<project>/node_modules/sails/node_modules/express/lib/application.js:514:14)
    at ServerResponse.res.render (/home/vagrant/nodeprojs/<project>/node_modules/sails/node_modules/express/lib/response.js:827:7)
    at ServerResponse.res.view (/home/vagrant/nodeprojs/<project>/node_modules/sails/lib/hooks/views/res.view.js:237:16)
    at Object.sendOK (/home/vagrant/nodeprojs/<project>/api/responses/ok.js:71:19)
    at ServerResponse.bound [as ok] (/home/vagrant/nodeprojs/<project>/node_modules/sails/node_modules/lodash/dist/lodash.js:729:21)
    at found (/home/vagrant/nodeprojs/<project>/node_modules/sails/lib/hooks/blueprints/actions/findOne.js:37:9)
    at wrapper (/home/vagrant/nodeprojs/<project>/node_modules/sails/node_modules/waterline/node_modules/lodash/index.js:3602:19)
    at applyInOriginalCtx (/home/vagrant/nodeprojs/<project>/node_modules/sails/node_modules/waterline/lib/waterline/utils/normalize.js:421:80)

And the User.js model. toJSON is commented out because the message originally pointed to that section. After commenting it out, line 3 (at User.attributes.toJSON) is now different.

var bcrypt = require ('bcrypt')
var User = {

    attributes: {
        email: {
            type: 'email',
            required: true,
            unique: true
        },
        password: {
            type: 'string',
            minLength: 6,
            required: true
        },
        admin: {
            type: 'boolean',
            defaultsTo: false // separate from acl
        },
        acl: {
            type: 'string',
            defaultsTo: 'USER' // MOD, USER (unlogged should get GUEST)
        }
/*
        toJSON: function() {
            var obj = this.toObject();
            delete obj.password;
            return obj;
        }
*/
    },

    beforeCreate: function(user, cb) {
        bcrypt.genSalt(10, function(err, salt) {
            bcrypt.hash(user.password, salt, function(err, hash) {
                if (err) {
                    console.log(err);
                    cb(err);
                } else {
                    user.password = hash;
                    cb();
                }
            });
        });
    }
};

module.exports = User;

[$E] After further review, I did an object-to-string conversion and output it at several points. The object on the first line of a try statement, and the first line of the subsequestn catch statement is this:

  waterline:toObject > this.object TRY=

>>>
email: admin@admin.com
password: $2a$10$bNktAvahfa3f8Q8lTV262u9RrLUqdvp7SzfM6dQqki3YliXdLMWxK
admin: true
acl: USER
createdAt: Fri May 29 2015 23:25:35 GMT+0000 (UTC)
updatedAt: Fri May 29 2015 23:25:35 GMT+0000 (UTC)
id: 1
_locals: [object Object]
<<<

 +2ms
  waterline:toObject > this.object CATCH=

>>>
email: admin@admin.com
password: $2a$10$bNktAvahfa3f8Q8lTV262u9RrLUqdvp7SzfM6dQqki3YliXdLMWxK
admin: true
acl: USER
createdAt: Fri May 29 2015 23:25:35 GMT+0000 (UTC)
updatedAt: Fri May 29 2015 23:25:35 GMT+0000 (UTC)
id: 1
_locals: [object Object]
<<<

(this output isn't supposed to be json, it's just a dump)

Unless someone has a better idea, I think I'm going to just move on over to the sailsjs issue tracker.

Travis Webb
  • 14,688
  • 7
  • 55
  • 109
monsto
  • 1,178
  • 1
  • 13
  • 26
  • there was an issue with `.toObject` fixed in https://github.com/balderdashy/waterline/pull/969. Can you please check your waterline version is equal or above v0.10.22? You can `cd` to `node_modules/sails/node_modules/waterline` and check the package.json. – Dário Jun 03 '15 at 14:02
  • @Dário: how do you specify that Sails should use a different version of Waterline? I can't see an easy way to do this... (I can do it locally I guess but the problem I'm having is on a server where `npm install` is run as part of the deploy process) – Nick F Jun 15 '15 at 16:06
  • You can try editing the `package.json` and specify the newer version, then doing a `npm install`. – Dennis Rongo Jun 19 '15 at 19:14
  • ...but the problem is that Waterline is specified in *Sails'* own `package.json`, not my project's. So the package.json that I'd have to change is one I don't have direct access to (it's added when I `npm install` my project). – Nick F Jun 23 '15 at 18:06

1 Answers1

0

I had this problem, and after a huge amount of trouble I've finally managed to fix it (I think it's now taken me as long to fix this bug as it took to build the app in the first place...)

Without seeing your Controller code, I don't know if this will fix it for you, but for me, the problem with toJSON seems to happen when feeding a User model into a partial. I found that explicitly rendering the model to JSON before passing it into the render function fixed the problem.

In other words, I changed this:

res.render('partials/user-card', user, function(err, html){
  partialData      = user.toJSON();
  partialData.html = html;

  // Send out a message (with HTML fragment) to socket subscribers
  User.publishUpdate(user.id, partialData);
});

...to this:

partialData = user.toJSON();

res.render('partials/user-card', partialData, function(err, html){
  partialData.html = html;

  // Send out a message (with HTML fragment) to socket subscribers
  User.publishUpdate(user.id, partialData);
});

(ie. move the user.toJSON out of the render function's callback, and feed the JSON rather than the model itself into the render function). This allowed me to retain the password-removing toJSON method too.

Nick F
  • 9,781
  • 7
  • 75
  • 90