4

Why does this code produce an TypeError: Object #<Object> has no method 'save'? The project object exists and is singular.

/** Update project */
exports.update = function (req, res, next) {
    var projectId = req.params.id;

    Project.findById(projectId, function (err, project) {

        if (project) {
            project.screens[0] = project.screens[0] || {};
            project.screens[0].name = 'Test screen';
            project.screens[0].data = req.body.data;
            project.save(function(err) {
                if (err) {
                    res.json(500, err);
                }
                else {
                    res.json(200, 'Update complete');
                }
            });
        }
        else {
            res.json(404, 'PROJECT_NOT_FOUND');
        }
    });
};

Schema:

'use strict';

var mongoose = require('mongoose'),
    Schema = mongoose.Schema;

var ProjectSchema = new Schema({
    name: String,
    slug: String,
    dateCreated: Date,
    dateUpdated: Date,
    createdByUserId: Schema.Types.ObjectId,
    screens: [ { name: String, data: Schema.Types.Mixed } ]
    //awesomeness: Number
    //Schema.Types.Mixed
    // ProjectSchema.methods.greet = function() { return 'Hello, ' + this.name; }; 
});

mongoose.model('Project', ProjectSchema);

Console output just before project.save:

Logged 'project': { name: 'My First Project',
  slug: 'my-first-project',
  dateCreated: Wed Jan 29 2014 22:26:22 GMT+0100 (CET),
  _id: 52e971fe003687a492000002,
  __v: 0,
  screens: [ { data: 'testWeld', name: 'Test screen' } ] }
2
  • I've done a workaround using Project.update instead. Commented Jan 30, 2014 at 15:10
  • I'm having the same problem, and I don't know how to solve it Commented Nov 3, 2014 at 22:16

2 Answers 2

2

I just completed debugging a problem with the same symptoms.

In your schema you have the following mongoose subdocument:

screens: [ { name: String, data: Schema.Types.Mixed } ]

I would agree with you that it would be intuitive if the following steps worked:

project.screens[0] = project.screens[0] || {};
project.screens[0].name = 'Test screen';
project.screens[0].data = req.body.data;

project.save(function(err) 

However, after re-reading the mongoose documents (Mongoose subdocs) the appropriate apis to add subdocuments need to be used as there is some casting/extra work that goes on.

For example, this got rid of the error message:

project.screens.push({ name: 'Test screen', data: req.body.data });

Hope that helps someone.

Sign up to request clarification or add additional context in comments.

Comments

0

Wasn't seeing the forest for the trees before. Glad you posted log output because now it's obvious something is logging. Save either takes no arguments or a three element callback which you can see in the documentation.

So your code should be more like:

// project.save(err) { <-- is an object and not a callback
project.save(function(err, project, numAffected) {
    if (err) {
        res.json(500, err);
    }
    else {
        res.json(200, 'Update complete');
    }
});

The whole Object#< Object > thing is because there is no reference at all. Hope that clears it up.

5 Comments

Sorry, still gives the same error. And me omitting the project, numAffected parameters shouldn't void the method call, based on what I know about JS methods. And Project.findById sure returns something...
Seems like project just contains the JSON structure and is not a proper Mongoose Model. Hmm...
I've done a workaround using Project.update instead.
Actually if you look at the code you posted you omitted the callback function, which is the only parameter to .save. Guessing you got the update call right then. BTW .save only differs from .update as what MongoDB calls an "upsert" which will insert or update an additional fields. But this is unlikely to matter to you under Mongoose.
The code reads project.save(function(err) { ... }); - that function is the callback, right?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.