meteor-astronomy icon indicating copy to clipboard operation
meteor-astronomy copied to clipboard

Required (and possibly other validators) not working on update

Open james1293 opened this issue 7 years ago • 2 comments

How to reproduce:

meteor create sampleAstro
cd sampleAstro
meteor add jagi:astronomy

Create /imports/posts.js with this content:

import { Mongo } from 'meteor/mongo';
import { Class } from 'meteor/jagi:astronomy';

const Posts = new Mongo.Collection('posts');

export const Post = Class.create({
  name: 'Post',
  collection: Posts,
  fields: {
    somenum: Number
  },
  secured:false
});

in server/main.js, add this line:

import '../imports/posts.js';

in client/main.js:

import { Post } from '../imports/posts.js';

var p1 = new Post();
p1.somenum = 3;
p1.save({cast:true});
var idForFinding = p1._id;

// just to give time for things to update
setTimeout(function(){
  var p2 = Post.findOne(idForFinding);

  console.log("Before changing:");
  console.log(p2); // somenum is 3

  p2.somenum = undefined;

  console.log("After changing:");
  console.log(p2); // somenum is undefined

  p2.save({cast:true});

  console.log("After saving:");
  console.log(p2); // somenum is undefined

  setTimeout(function() {

    console.log("finding again:");
    console.log(Post.findOne(idForFinding)); // somenum is 3

  }, 2000);
}, 2000);

Expected behavior:

p2 is not allowed to be saved because fields are required by default, so undefined should not be allowed to be saved. In other words, .save() should throw.

Actual behavior:

Modification of the document fails, but does not throw.

Some info from my attempt to figure out what was wrong:

When p2.save() is called, it calls the meteor method which ultimately validates the document. However, it doesn't seem to be passing in the modified copy of the document, only a selector (methodArgs.selector, which in this case contains the _id) that can be used to find the document.

I stepped through using the debugger, and sure enough, it is validating the fields of the old document. Line 48 of class_update.js uses the aforementioned selector to fetch the document to be validated using Class.find(). This is the old copy of the document, which you can see when this document is passed into documentUpdate() on line 84. That old copy is what ultimately gets validated.

I'm not sure why the save ultimately fails.

Hope that helps, thanks!

james1293 avatar Jul 28 '17 18:07 james1293

Also, in case anyone else is having this problem, here's a workaround:

// add doc.validate() just before doc.save()
// doc.validate() throws correctly, and will prevent .save() from running
doc.validate({cast:true}); 
doc.save({cast:true});

james1293 avatar Jul 28 '17 18:07 james1293

You set secured to false. Have you tried with this flag set to true? Could you also create reproduction repository?

lukejagodzinski avatar Jul 30 '17 18:07 lukejagodzinski