Set default value of validation - javascript

I am using Joi to validate a payload of a service in my node.js server using hapijs framework. It used to look like this (in my typescript code as well as after compiling to javascript):
payload: {
para1: Joi.number().required(),
para2: Joi.string()
}
Now I want to set default value of the two parameters. If the code is written in javascript, I can do this:
payload: {
para1: Joi.number().required().default(1),
para2: Joi.string().default("defaultstring")
}
I tested it in swagger and the default values actually became the values I set.
However, my project is written in typescript. I did the same thing and compiled typescript code. The result javascript looks like this:
payload: {
para1: Joi.number().required()["default"](1),
para2: Joi.string()["default"]("defaultstring")
}
In swagger, the default values are not applied.
Here are my questions:
why the code becomes different after compiling?
what does ["default"]("defaultstring") mean and what does it do?
how can I write typescript code to make sure it can compiled as Joi.string().default("defaultstring")
Update
According to #rsp's post, the format in question 2 is just different way to access object's property. I also get reference from here. But it doesn't explain if they have any difference. Does anyone have any idea?
Update2
Here is the difference between the two ways accessing JS property. It seems there is no negative effect using brackets way. However, in my case, the default values are not reflected on swagger. Will be doing research on it.

In JavaScript this:
required().default(1)
is the same as this:
required()["default"](1)
because you can access object properties either as:
object["propertyName"]
or:
object.propertyName
(with certain restrictions in the second case).
So it's strange that TypeScript would output the longer style if it doesn't have to, but it's also strange that the longer style doesn't work exactly the same as the shorter one.
I would try to manually change the compiled JavaScript to the shorter version and see if that helps. If it doesn't then the problem is somewhere else. My suspicion is that it will not help.
The .default() should work in TypeScript because it is defined in #types/joi - see:
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/joi/index.d.ts#L272-L273
But on the other hand there is this comment:
// TODO express type of Schema in a type-parameter (.default, .valid, .example etc)
Which may suggest that .default() implementation is not ready yet - see:
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/joi/index.d.ts#L6
and also there's this issue: joi.d.ts out of date, missing types
https://github.com/DefinitelyTyped/DefinitelyTyped/issues/9332

Use should use default() like in below code:
validate: {
payload: {
para1: Joi.number().integer().min(1).max(100).default(10).required(),
para2: Joi.string().min(1).max(100).default("TEST").required(),
}
}

It still says key is required when we use Joi.boolean().required().default(true)
The below worked for me
JOI.boolean().default(false)

taxAmount: Joi.number().default(0),
totalAmount: Joi.number().default(0),
This works for me. Do not use .reqquired() keyword.
The result will be in the
const validationResult = schema.validate(data);
validationResult.value

Related

Custom Unobtrusive Validation Method Not Firing as Per Documentation

I've been attempting to implement a ASP.NET MVC custom validation method. Tutorials I've used such as codeproject explain that you add data-val-customname to the element. Then jQuery.validate.unobtrusive.js then uses the third segment of the attribute
data-val-<customname>
as the name of the rule, as shown below.
$.validator.addMethod('customname', function(value, element, param) {
//... return true or false
});
However I just can't get the customname method to fire. By playing around I have been able to get the below code to work, but according to all the sources I've read Unobtrusive validation should not work like this.
$.validator.addMethod('data-val-customname', function(value, element, param) {
//... return true or false
});
I've posted an example of both methods
jsfiddle example
Any help would be much appreciated
I've updated my question hopefully to make clearer.
I have finally found got there in the end, but still feels like too much hard work and therefore I've probably got something wrong. Initial I was scuppered by a bug in Chrome Canary 62 which refused to allow the adding of a custom method.
My next issue was having to load jQuery, jQuery.validate and jQuery.validate.unobtrusive in the markup and then isolate javascript implementation in a ES6 class. I didn't want to add my adaptors before $().ready() because of my class structure and loading of the app file independent of jQuery. So I had to force $.validator.unobtrusive.parse(document);.
Despite this I was still having issues and finally debugged the source code and found that an existing validator information that is attached to the form was not merging with the updated parsed rules, and essentially ignoring any new adaptors added.
My final work around and admit feels like I've done too much, was to destroy the initial validation information before my forced re-parse.
Here is the working jsfiddle demo
Here is some simplified code
onJQueryReady() {
let formValidator = $.data(document.querySelector('form'), "validator" );
formValidator.destroy();
$.validator.unobtrusive.adapters.add("telephone", [], function (options) {
options.rules['telephone'] = {};
options.messages['telephone'] = options.message;
});
$.validator.unobtrusive.parse(document);
$.validator.addMethod("telephone", this.handleValidateTelephoneNumber);
}

how validation works in mongoose

I was reading documentation of mongoose: http://mongoosejs.com/docs/guide.html
It is said that validation occurs before saving document in the database.
And to turn this feature off we have to set option: validateBeforeSave to false.
However I have another decent Node.js tutorial example where they just use .validate as follows:
var course = new Course({});
course.validate(function(err) {
assert.ok(err);
assert.equal(err.errors['title'].kind, 'required');
course.title = 'Introduction to Computer Science';
assert.equal(course.title, 'Introduction to Computer Science');
var s = '0123456789';
course.title = '';
while (course.title.length < 150) {
course.title += s;
}
course.validate(function(err) {
assert.ok(err);
assert.equal(err.errors['title'].kind, 'maxlength');
++succeeded;
done();
});
});
I can't understand the underlying reason for using validate without setting validateBeforeSave option to false? Could someone please clarify how the provided code above works?
validateBeforeSave, as the name implies, validates the mongoose object before persisting it to database. This is a schema level check, which, if not set to false, will validate every document. It includes both built-in (like a Number cannot contain string or a required field should exist etc.) and custom defined validations.
validate does the same, only it has no concern with saving the document afterwards. It's the method on the object which you invoke, like course.validate(callback), and get to know if the object is valid or not through err in the callback.
Both are doing one and the same thing but at different times and different level. Also, both are not mutually exclusive, so one does not need to be set off for other to work.
As for the use case of validate, unit testing is one example. You may want to test your validators without the trouble of mocking save or setting up a test database. I believe the example is trying to do something like that, though not in a structured way.
As you said mongoose is fireing up validation before save operation, but there are some cases when you want to validate document schema without save. For this you can use validate method directly.
Your example from tutorial show us piece of code representing unit tests. So for example we can check methods which generate some model to save without saving him.
Also validate method could help when you have complicated action flow with many saves and dependencies. For example you want to save user dashboard model with proper structure but firstly you saving user profile. With validate method and for instance wrong dashboard structure you can check request and throw exception before saving user profile.
In the example code, they are using Async Custom Validator which you would understand better if you check this: http://mongoosejs.com/docs/validation.html#built-in-validators
They are used when standard validation is not enough and this is purely my observation that they are usually used in testing along with some testing framework and assetion library.

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? Edit: Edit: This works, you can write everything out long-form with all of this extra boiler plate if you want to avoid validation all together for the time being. For now this is the solution I will use until I finally decide on how I will be validating everything. I'm not sure what to do right now because Simple Schema is in transition. - Actually that doesn't work, it for some reason never returns a value and I couldn't get around that.
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.
You could re-implement SimpleSchema's API, but why?
SimpleSchema is a de facto standard in Meteor, like Mongoose for Node<->MongoDB. There are alternatives in the works, but I think you're pushing the bleeding edge.
If you've got work to do, use SimpleSchema.
From the Meteor Forums:
Firstly, the Meteor method should expect an object like so:
myMethod.call({
arg1: 'hello',
arg2: 25,
}, (error, result) => { /* do stuff */ });
And then your method would be defined as such: (Note, that validate() { } is empty, before I was returning true - this was the problem I was having)
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,
}
},
And this way we can avoid using Simple-Schema while it works out it's transition from 1.0 to 2.0 (Good luck Simple Schema!!!)
And thanks to ffxsam for providing the solution on the meteor forums!

Node JS Inspect shows property has value but inspecting property returns undefined

I'm working on a Node JS app, using Coffeescript and Mongoose with a MongoDB database.
I have a Mongoose model like this:
Client = mongoose.model 'Client', mongoose.Schema
# Basics
name: String
email: String
api_key: String
# Modules enabled / disabled
modules: Object
# Settings for modules
reporting: Object
filter: Object
templates: Object
datatypes: Object
The modules property is an object containing keys with a boolean indicating whether or not a module should be loaded (see the console.log output a bit further in this post). The four properties below that are the settings for the specific modules.
When my app starts, I load this information for the current user, and assign the data to a config variable like this:
config.name = clients[0].name
config.api_key = clients[0].api_key
config.modules =
reporting_enabled: clients[0].modules.reporting
filter_enabled: clients[0].modules.filter
templates_enabled: clients[0].modules.templates
datatypes_enabled: clients[0].modules.datatypes
Now the first three of these modules work perfectly. I coded them about a week ago and nothing was wrong. But I'm adding the datatypes module now, and I'm running into a very strange problem.
Whenever I try to access the clients[0].datatypes property it returns undefined but when I do console.log clients[0] it will show me all the properties, and their values, including datatypes.
Part of the output of console.log clients[0]:
modules:
{ datatypes: true,
templates: true,
filter: false,
reporting: true },
reporting:
{ email_interval: 2,
name: '___',
email: '___',
send_email: true },
filter: {},
templates: { cms: { contacts: [Object] } },
datatypes: { cms: { contacts: [Object] } }
So as you see, there's all the properties including datatypes. Of these I can access the modules, reporting, filter and templates properties without any problem (using clients[0].modules for example), but when I want to access the datatypes property clients[0].datatypes it will return undefined.
I have triple-checked that I'm writing 'datatypes' correctly, and that it's not an async function that messes with me. I put the log right before the line where I actually want to use .datatypes, and no async stuff is going on at that point, so that isn't it. I tried some other things, changing the loading order etc, but nothing works.
console.log clients[0]
console.log clients[0].datatypes
That first line outputs my whole object including the datatypes property. The second one keeps saying undefined.
I think this may have something to do with Node or Mongoose, or it's one of those Javascript quirks, or perhaps (just as likely) it's just me being an idiot and messing something up. I really don't know and I've been searching for a solution for around two hours now, done something of a hundred google searches, went digging through StackOverflow and other websites, but I couldn't find an answer to my problem and couldn't fix it myself. Does anyone here know what might be causing this issue?
For anyone else having this problem, the fix for me was to call .toObject() on the Mongoose result: client[0] = client[0].toObject(). This transforms the Mongoose object into a regular object.
To me it is still a bit of a mystery why all the other properties could be addressed fine without this, but that one property wouldn't. But .toObject() solved this problem for me.

"Error calling method on NPObject!" in Uploadify

I'm using Uploadify to upload file in my CMS. Everything works fine until recently. I got an error
Error calling method on NPObject
on this line
document.getElementById(jQuery(this).attr('id') + 'Uploader').startFileUpload(ID, checkComplete);
on this part
uploadifyUpload:function(ID,checkComplete) {
jQuery(this).each(function() {
if (!checkComplete) checkComplete = false;
document.getElementById(jQuery(this).attr('id') + 'Uploader').startFileUpload(ID, checkComplete);
});
},
I don't know why and after a day debugging and testing I found that if I remove replace(/\&/g, '\\&') from
String.prototype.escAll = function(){
var s = this;
return s.replace(/\./g, '\\.').replace(/\?/g, '\\?').replace(/\&/g, '\\&');
};
It then works again. I really don't know why.
Any helps would be appreciated!
I think the reason is in additional Javascript libraries you use.
Some libraries (for example Prototype.js or jQuery.js) change behaviour of your code. For example, you can't overload prototype in some cases. The result may be undefined in clear (obvious) places (like you use an array variable with wrong index). You should view the source code of additional libraries, probably they do with prototype something that breaks your code in the function you mentioned.
In my practice I had the situation when overloading of prototype worked incorrectly (it was String prototype like in your case).
So just don't use prototype.

Categories

Resources