In working to take advantage of ValidatedMethod, I was disturbed by the repetition of schema validation code that was already present elsewhere in the validate member of the method. A short look at SimpleSchema revealed that the “pick” function should provide the answer to that. I even saw several clues that efforts were made to enable exactly the approach I was imagining with ValidatedMethod and SimpleSchema and I wonder why they weren’t illustrated in the guide. IMO, best practice would never have duplicated schema definitions that could be shared.
Anyway, I set out to utilize pick to reuse my schema and thought that all was going well… until I tested.
I want my “insert” method to require “name”, allow “description” to be undefined, and “visibility” to default to “private” if not specified. This is exactly what my SimpleSchema definition provided for, so I figured all would be good. I set validate to “Groups.schema.pick([‘name’, ‘description’, ‘visibility’]).validator()” and thought all was good. But, the “visibility” option wasn’t defaulting as defined by my Groups schema.
After digging through the docs, I found that the defaultValue is implemented in the clean stage of SimpleSchema processing and that stage isn’t run by validator(). So, my problem isn’t with “pick”, it is with “validator”. Luckily, aldeed added a “clean” option to validator() in December. Turning on “clean” allows the defaultValue to have effect. Awesome.
The problem I now have is that the “clean” stage is too thorough. It is cleaning away undefined keys without giving any error indication to the caller. This can cause a lot of head pounding when a developer has a typo in a key.
So, does anyone know how to get SimpleSchema to validate while both implementing defaultValue and complaining about fields that aren’t present in the schema?
Hopefully, I’ve excerpted enough of my code below to give a flavor of what is happening.
Groups.schema = new SimpleSchema({
name: {
type: String,
},
description: {
type: String,
optional: true,
},
visibility: {
type: String,
allowedValues: [
'public',
'community',
'private',
],
defaultValue: 'private',
},
});
export const insert = new ValidatedMethod({
name: 'groups.insert',
validate: Groups.schema.pick([
'name',
'description',
'visibility']).validator({ clean: true }),
run({ name, description, visibility }) {
const group = {
name,
description,
visibility,
};
return Groups.insert(group);
},
});
// this fails without "{ clean: true }" on validator call above.
groupId = insert._execute(
{ userId: 'test-user' },
{ name: 'goodname', description: 'good description' }
);
// this works with "{ clean: true }", but I don't want it to.
insert._execute(
{ userId: 'test-user' },
{ name: 'goodname', badField: 'no such field' }
);