Skip to content
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

Fix dot notation with coerce #57

Merged
merged 2 commits into from
Sep 8, 2016
Merged

Fix dot notation with coerce #57

merged 2 commits into from
Sep 8, 2016

Conversation

maxrimue
Copy link
Member

This PR attempts to fix yargs/yargs#599.

While the newly added test now passes, two other tests now fail. I haven't figured out yet why they fail, hence this is a WIP PR.

@bcoe
Copy link
Member

bcoe commented Aug 30, 2016

@maxrimue, I like @nexdrew's approach to explicit arrays:

it('applies coercion function to an explicit array', function () {

The coerce function gets passed the entire array, which it can then apply a map on. For the sake of consistency, I think it would be neat if:

  • coerce got passed the entire object, if an object has been built using dot notation.
  • I also think that we should make it so implied arrays: -f 33 -f 99 get passed as a whole array to the coerce function -- this would be more consistent.

What do you both think?

@maxrimue
Copy link
Member Author

@bcoe I'm not fully sure if I get you right, do you mean that inside the setKey function, it should apply coercions to dot options when the parent option is being processed?

If this is what you mean, I'm not sure if I like that approach too much. The problem I see here is that it might appear weird that dot options get their coercion function's return value not when they are being processed, but when the parent gets processed, even though all of them run through setKey once.

Also, this would mean that if I set a coerce function for foo and maybe create a dot option foo.bar, bar would have to cope with foo's coerce function even though people might want different coerce functions.

For example, if I have the option user with sub options like id, password email and whatever, chances are high I need to transform values differently for all of them, if at all.

@bcoe
Copy link
Member

bcoe commented Aug 31, 2016

@maxrimue I would like @nexdrew's feedback on this too, but it seems more consistent to me if we apply the coercion method to the already built array, or object, rather than key by key -- the nice thing, is you can then lean on built in functions like Object.map, Array.map, which feels more natural.

@bcoe
Copy link
Member

bcoe commented Aug 31, 2016

@maxrimue I would like @nexdrew's feedback on this too, but it seems more consistent to me if we apply the coercion method to the already built array, or object, rather than key by key. This feels fairly elegant:

yargs.coerce('o', function (obj) {
  return obj.map(function () {}) // some transformation on the object.
})

rather than something like

yargs.coerce('o.banana', function () {})

This would put us in a better position to apply a different transformation for a key such as password:

yargs.coerce('o', function (obj) {
  if (obj.password) obj.password = '[Secret]'
  return obj
})

@bcoe
Copy link
Member

bcoe commented Aug 31, 2016

@nexdrew @maxrimue mainly I'd like to see us go all one way or the other for arrays and objects, based on @nexdrew's arguments here:

#50

This includes updating how the parser handles implicit arrays, what do you think?

@nexdrew
Copy link
Member

nexdrew commented Sep 2, 2016

I agree that it would be better to coerce the fully-realized object once rather than coerce individual properties separately, mainly because the former is a superset of the latter (i.e. you can still handle individual properties separately when processing the full object, but you can't handle the full object when processing individual values only).

I've been on the fence about implicit arrays, mainly because it seems the author did not intend for the parsed value to be an array, but I've realized the whole point of coercion is to transform the complete parsed value into the desired form, so the author can choose how to slice & dice a potential array during coercion (e.g. give precedence to the first or last value) rather than when actually trying to use the value in argv. So, all that to say yes, I'm in favor of coercing implicit arrays as an array instead of as individual values.

Based on this, I think we need to drop all coercion from the setKey function and, instead, apply coercion as pure post-processing after all args have been parsed. So basically change applyArrayCoercions into something that applies all coercions, to support implicit arrays and args nested within objects.

@maxrimue
Copy link
Member Author

maxrimue commented Sep 5, 2016

I tried it again and this time implemented as you suggested. @bcoe, I used this approach as an example for usage you provided:

yargs.coerce('o', function (obj) {
  if (obj.password) obj.password = '[Secret]'
  return obj
})

You can see in the test that it's similar what I do there. However, I needed to change one other test, you can see that instead of iterating over each value of a passed array, it now expects the entire array to be passed back from the coercion function, which is why the test broke, and I changed it accordingly.

Is this what you had in mind, @bcoe and @nexdrew?

@nexdrew
Copy link
Member

nexdrew commented Sep 6, 2016

This LGTM! Nice work, @maxrimue! What do you think @bcoe?

@bcoe
Copy link
Member

bcoe commented Sep 8, 2016

@maxrimue @nexdrew looks great to me!

@bcoe bcoe merged commit 4ca69da into master Sep 8, 2016
@bcoe bcoe deleted the fix-dot-notation-with-coerce branch September 8, 2016 02:36
@bcoe bcoe changed the title [WIP] Fix dot notation with coerce Fix dot notation with coerce Sep 15, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Dot-notation is not processed via coerce()
3 participants