-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for truthy/falsy boolean values #998
Conversation
@@ -808,6 +810,24 @@ const boolean = Joi.boolean(); | |||
boolean.validate(true, (err, value) => { }); | |||
``` | |||
|
|||
#### `boolean.truthy(value)` | |||
|
|||
Allows for additional strings to be considered valid boolean values in addition to default 'truthy' strings: ['true', 'yes', '1', 'on']. Accepts a string or an array of strings. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally, I don't think this should be additional
as I want to be able to be explicit about it. Instead I think this should override the valid truthy
values instead of just add new ones.
The same goes for the falsey
one below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I get that. It is currently (in this PR) implemented as additive, so that I didn't nuke the strings that are already type-coerced by the "vanilla" boolean schema type. Here's where the "additive" piece is in the code: https://github.com/hapijs/joi/pull/998/files#diff-3b86748616af947ebd7969eedec0062aR76
I'm totally down for overriding the default type-coerced strings. I was just trying to play nice with what was already in place. Just let me know what would be preferred and I will update accordingly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like I said in the issue, I don't mind it being a breaking change, so default true/false and additive calls to stay consistent with valid/invalid makes the most sense to me.
|
||
```js | ||
const boolean = Joi.boolean().truthy('Y'); | ||
boolean.validate('Y', (err, value) => { }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing boolean.validate('Y', (err, value) => { }); // valid
or something else might help to show that this works.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure thing. On it, thanks.
Why only allow string values? |
return value.toLowerCase(); | ||
}); | ||
} | ||
else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just cast the value to an array if it isn't one currently? That way you don't have the code repeated. So before line 62 something like: truthyValue = Array.isArray(truthyValue) ? truthyValue : [];
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call. I'll do that along with the API.md update above. Thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually inconsistent with how we do it everywhere else, see https://github.com/hapijs/joi/blob/master/lib/any.js#L235.
@AdriVanHoudt Simply because that was what was discussed in the feature request issue. And I thought a simple initial implementation would be best for a new feature PR. It can always be extended in the future if the need for non-string values arises. |
@WesTyler I see your point, although feature wise it would seem weird to limit it (if you are not involved with the original issue) |
Agreed with @AdriVanHoudt here, I thought my pov was clear in the original issue, sorry for that. |
@Marsup Ah, gotcha. I misunderstood what you meant in the issue about it being a breaking change. Updating right now per your 3 comments above. Thanks for the input! |
Now that I just pushed that though, I'm wondering if the Thoughts? |
@WesTyler yes, this might be a good idea. Careful with cloning though, you'll have to implement a slice equivalent (https://github.com/hapijs/joi/blob/master/lib/any.js#L110) because _inner properties are meant to be arrays. |
This might also be a challenge for concat() and describe() which are currently lacking in the PR. Joi is a complex beast :) |
Alright, I extracted the Set class out of any.js into its own file, and implemented it for the boolean inners. I also implemented I added boolean-specific tests around |
|
||
const Ref = require('./ref'); | ||
|
||
const Set = class { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you make this exports.Set ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@WesTyler oh my, sorry, I was thinking module.exports = class, just bypassing the local constant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haha, my bad. Yeah I'll do it that way.
return result; | ||
} | ||
|
||
_truthy() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you split both truthy and falsy ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just following the pattern set with _allow
and allow
in Any. I can un-split them if you prefer though; going to leave it as-is unless you specifically want them combined @Marsup :)
|
||
result.value = (value === 1 ? true | ||
: (value === 0 ? false : value)); | ||
if (this._inner._truthySet.values().length) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
values() is already a copy, so I guess description.truthyValues = this._inner._truthySet.values()
is enough.
slice() { | ||
|
||
const newSet = new Set(); | ||
newSet.merge(this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
merge will be slower, a simple newSet._set = this._set.slice()
would be better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright cool. Wasn't sure if it was kosher to access the private _set
from outside the class. Definitely agree with you though. I'm on it, along with other requested revisions.
concat(source) { | ||
|
||
const newSet = new Set(); | ||
newSet.merge(this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, probably newSet._set = this._set.concat(source._set)
.
I thought I had already left this comment, but I don't see it now. So here goes again. The |
Can't remember why _allow is this way but I see no reason to do that. |
Alright, I'll update truthy/falsy then. Would you like me to go ahead and re-combine _allow/allow in Any while I'm at it? |
Nah let's keep this PR focused, I'll do it someday :) |
Alright, pushed the removal of Boolean's _truthy/_falsy pattern. |
@Marsup Is there anything else you're waiting on me to fix/update/refactor? Not trying to rush you, just making sure you're not waiting on me :) |
Almost perfect, I'll deal with the bits I don't like myself. Thanks a lot ! |
LMK if you see anything shocking to you in my cleanup. |
Awesome! Thanks for the patience and guidance on this! :D Cleanup makes sense to me. |
This thread has been automatically locked due to inactivity. Please open a new issue for related bugs or questions following the new issue template instructions. |
This commit resolves #991 by adding the following support:
Joi.boolean().truthy()
andJoi.boolean().falsy()
Hoek.assert
to ensure that the values passed are strings.