[Solved] Meteor mdg:validated-method without using simple schema

Well,

Simple Schema is in the middle of transitioning to a new version 2.0

And at the same time, I’m not really sure I’d like to use this in my project.

I am writing an ES6 React based Meteor application therefor I’d like to make use of The “Advanced” way to create meteor methods. However, I don’t want to use aldeed:simple-schema at all.

Is there a way to put in a custom validation method here?

This doesn’t work:

export const addSuggestion = new ValidatedMethod({
  name: 'suggestion.add',
  validate() {
    return true
  },
  run(incommingSuggestion) {
    // do things which are not relevant to this question.
  }
})

It produces the following error:

Error: Returning from validate doesn't do anything; perhaps you meant to throw an error?(…)

Is there a different way to write this?

Perhaps I need to not use this validated-method, instead I should maybe write it out long-form?

Anyone out there know how to get around this?

Obviously googling has not turned up any results, I’ve been looking at this problem now for more than three days.

This is also posted on stackoverflow.

First off, you want to pass an object to a validated method, e.g.:

myMethod.call({
  arg1: 'hello',
  arg2: 25,
}, (error, result) => { /* do stuff */ });

And then your method would be defined as such:

import { ValidatedMethod } from 'meteor/mdg:validated-method';
import { check } from 'meteor/check';

export const myMethod = new ValidatedMethod({
  name: 'myMethod',
  validate() { }, // always valid
  run({ arg1, arg2 }) {
    // do things
  }
};

When you’re ready to validate the arguments, just change validate accordingly:

  validate(opts) {
    check(opts, {
      arg1: String,
      arg2: Number,
    }
  },
1 Like

I’m using Joi (browser version) and a custom mixin:

export const joiValidation = function (methodOptions) {
  if (methodOptions.schema) {
    methodOptions.validate = (data) => {
      const result = methodOptions.schema.validate(data, { stripUnknown: true });
    
      if (result.error) {
        throw new ValidationError(result.error.details.map(error => {
          // map joi error to ValidationError
          return {
            name: error.path,
            type: error.type,
            message: error.message
          };
        }));
      }

      // call validatedMethod.run with the validated/cleaned values!
      const runFunc = methodOptions.run;
      methodOptions.run = function () {
        return runFunc.bind(this)(result.value);
      }
    }
  }

  return methodOptions;
};

One advantage of this setup is that i can reuse the Joi schema for form validation with redux-form.

1 Like

Thank you so much @ffxsam - You dispelled the blackbox for me! That works perfectly.

and @Chris.R Thank you for the Joi suggestion - I never knew about this and I’ve heard good things about Hapijs. I really like how friendly their documentation is! Thanks so much - I might use this in the future.

For now - check/match will get me all the way I need to go.

1 Like

I think this is a good place to ask: Is it possible to create a ValidatedMethod with optional arguments and run the validation only when they’re there?
I think I’ve tried this and ran into a couple of problems. Not only with the validation itself, but whit the run({ arg }) part, which threw an error if there was no argument.

Thanks!

Have you tried something like:

validate(args) {
  if (!args) return;

  check(args, {
    name: String,
    location: Match.Optional(String),
  });
},