Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When exactly does Mongoose's .pre('init') get called?

I want to create 'games' which each have their own unique access 'code'. The code is required in the schema, and I need to generate a code each time a new game is created.

I thought schema.pre('init') would be a good place to generate this access code:

GameSchema.pre('init', function(next) {
    // Code generation logic happens here
    this.code = myNewlyGeneratedCode
    next()
}

Unfortunately, this returns an error message: ValidationError: Game validation failed: code: Path 'code' is required.

Why doesn't this work? Do I have to just create a code before I instantiate a new game?

like image 793
Delta_HF Avatar asked Dec 23 '22 08:12

Delta_HF


1 Answers

As mentioned in the comments, pre('save') is the middleware that runs before your document gets stored in the db. pre('init') gets called on your documents when they are returned from mongodb queries.

The easiest way to demonstrate the order of document middleware is with a simple example:

49768723.js

#!/usr/bin/env node
'use strict';

const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
const Schema = mongoose.Schema;

var count = 0;

const schema = new Schema({
  name: String
});

function log(str) {
  console.log(`${++count}: ${str}`);
}

schema.pre('save', function () {
  log('pre-save');
});

schema.pre('init', function () {
  log('pre-init');
});

schema.post('save', function () {
  log('post-save');
});

schema.post('init', function () {
  log('post-init');
});

schema.pre('validate', function () {
  log('pre-validate');
});

schema.post('validate', function () {
  log('post-validate');
});

schema.pre('remove', function () {
  log('pre-remove');
});

schema.post('remove', function () {
  log('post-remove');
});


const Test = mongoose.model('test', schema);

const test = new Test({ name: 'Billy' });

async function main() {
  await test.save();
  log('saved');
  await Test.findOne({ _id: test.id });
  log('found');
  await test.remove();
  log('removed');
  return mongoose.connection.close();
}

main();

output

stack: ./49768723.js
1: pre-validate
2: post-validate
3: pre-save
4: post-save
5: saved
6: pre-init
7: post-init
8: found
9: pre-remove
10: post-remove
11: removed
stack:
like image 63
lineus Avatar answered Dec 26 '22 00:12

lineus