Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript Build a REST API With Express Modeling Data for the API Getting More from Mongoose

Damian Wynter
Damian Wynter
15,803 Points

pre.save() not working

'use strict';

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/sandbox');

var db = mongoose.connection;
db.on('error', (error) =>{
    console.log('connection error: ', error);
});

db.once('open', () => {
    console.log('database connection was successful');
    // Database codes goes here...

    var schema = mongoose.Schema;

    // Creating default values for mongoDB with mongoose
    var animalSchema = new schema({
        type:  {type: String, default: 'goldfish'},
        color: {type: String, default: 'golden'},
        size: String,
        mass:  {type: Number, default: 0.007},
        name:  {type: String, default: 'goldy'}
    });

    animalSchema.pre('save', (next) => {
        console.log(this);
        if(this.mass >= 100){
            this.size ='big';
        } else if(this.mass >= 5 && this.mass < 100){
            this.size = 'medium';
        } else {
            this.size = 'small';
        }
        next();
    });

    var Animal = mongoose.model('Animal', animalSchema);

    var elephant = new Animal({
       type: 'elephant',
       color: 'gray',
       mass: 250,
       name: 'lawrence'
    });

    var animal = new Animal({}); // create goldfish

    var whale = new Animal({
        type: 'whale',
        mass: 1500,
        name: 'jessie'
    });

    var animalData = [
        {
            type: 'mouse',
            color: 'gray',
            mass: 0.032,
            name: 'marvin'
        },
        {
            type: 'nutria',
            color: 'brown',
            mass: 6.35,
            name: 'gretchen'
        },
        elephant,
        animal,
        whale
    ];

    Animal.remove({}, (error) => {
        if(error){
            console.error(error);
        }
        Animal.create(animalData, (error, animals) => {
            if(error){
                console.error(error);
            }
            Animal.find({}, (error, animals) => {
                animals.forEach((animal) => {
                    console.log(`${animal.name} the ${animal.color} ${animal.type} and is a ${animal.size}-sized animal.`)
                    });
                db.close(() => {
                    console.log('database closed');
                });
            });
        });
    });
});

When i log 'this' it contains a blank object, then it assigns the key value pair containing small to the object. Any help? Thanks Guys

2 Answers

Seth Kroger
Seth Kroger
56,414 Points

Due to the nature of this in an arrow function you can't use them for Mongoose hooks. this in arrow functions aren't rebindable, but Mongoose wants to rebind this to be the document being saved. You should use an anonymous function instead (i.e., function() {})

Damian Wynter
Damian Wynter
15,803 Points

Thank you so much for the assistance, i really did not know that

Is there another way to access the document other than this? Maybe a 2nd parameter other than the next middleware?

I feel like mongo trying to rebind this is a smell (but I'm just a newbie to node, who am I to judge)

Is there any way to bind this to the object that 'save' calls on? It is just strange that you cannot use arrow function in 2017 in any modern frameworks. I did: user.bind(this), but didn't work.

On stackoverflow, one person commented that " () => is not the new 'function()'! " in ES6. Is there a good rule of thumb when to use ()=> vs. function() ? I've seen workarounds for 'this' in arrow functions, but I don't know how to properly use 'this' in arrow functions or whether to avoid 'this' altogether and just use function() in those cases....