-
Notifications
You must be signed in to change notification settings - Fork 70
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 Slop::Result#fetch #232
Add Slop::Result#fetch #232
Conversation
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.
Spelling note.
lib/slop/result.rb
Outdated
@@ -20,6 +20,11 @@ def [](flag) | |||
end | |||
alias get [] | |||
|
|||
# Returns an options value, raises KeyError if the option does not exist. |
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.
options
=> option's
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.
Thanks, fixed here and in Slop::Result#[]
description!
Hash#fetch implements a few more behaviors, are you interested in those, too? |
I take a look at it but I think that is a good option to not allow a default value when a given key does not exists, primarily because you know beforehand all the keys that you'll have and you can also specify default values for those keys. What do you think @olleolleolle? |
@giovannibenussi I usually raise a more specific error message or specific error class in |
(But, this was a question, not a judgement.) |
No worries :-) ! I'll take
For the case of Let me know you thoughts :-) |
I notice that if you declare an option as not required without a default value and don't set it, then opts = Slop.parse do |o|
o.string '-name'
end
ARGV #=> ''
opts.fetch(:name) # raises KeyError: key not found: 'name' I think that in this case then |
I made some changes so now |
lib/slop/result.rb
Outdated
def fetch(flag) | ||
o = option(flag) | ||
if o.nil? | ||
raise(KeyError.new(%Q(key not found: '#{clean_key(flag)}'))) |
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.
can also be expressed as
raise KeyError, %Q(key not found: '#{clean_key(flag)}')
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.
What about:
raise KeyError, "key not found: '#{clean_key(flag)}'"
I think that I was using %Q
because at some point I wanted to show an error message like key not found: "key"
but it is no longer necessary.
How do you feel about this changes? Regards! |
lib/slop/result.rb
Outdated
def [](flag) | ||
(o = option(flag)) && o.value | ||
end | ||
alias get [] | ||
|
||
# Returns an option's value, raises KeyError if the option does not exist. | ||
def fetch(flag) | ||
o = option(flag) |
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 could be simpler because we already support the functionality in Result#[]
:
def fetch(flag)
get(flag) or raise KeyError, "key not found: '#{clean_key(flag)}'"
end
Also I don't think the message is clear enough. I would opt for something like "Could not find option with flag '#{flag}'". I don't think the flag needs cleaning either, but I'm not too bothered either way. Also, any reason we shouldn't just re-use Slop::UnknownOption
since it basically means the same thing?
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.
get(flag) or raise KeyError, "key not found: '#{clean_key(flag)}'"
will throw an exception if the value of the key flag
is nil this happens when you don't provide an option and that option does not have a default value as I test in test/result_test.rb:
it "returns nil when an option is not provided and it does not have a default value" do
@options.string("--hello")
@result.parser.parse %w()
assert_equal nil, @result.fetch('hello')
end
I tried to remove clean_key(flag)
but if you try to make something like @result.fetch("--unexisting")
then you'll receive the following error: key not found: '--unexisting'
.
As for Slop::UnknownOption
, I think that I don't express well enough the purpose of Slop::Result#fetch
. The idea of Slop::Result#fetch
is the same as []
and get
, but with the difference that an exception is thrown if a defined argument is not provided, with the aim of avoid typos. So I think that Slop::UnknownOption
is not appropiated here because this exception as far as I understand is raised when you try to fetch an undefined argument.
Related with the previous paragraph, maybe your proposal of "Could not find option with flag '#{flag}'"
is not accurate enogh, but I'm open to suggestions anyways :-)
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.
will throw an exception if the value of the key flag is nil this happens when you don't provide an option and that option does not have a default value as I test in test/result_test.rb
Right, good catch!
I tried to remove clean_key(flag) but if you try to make something like @result.fetch("--unexisting") then you'll receive the following error: key not found: '--unexisting'.
Yeah, I think that's okay. As I mentioned though, I don't feel too strongly about it so feel free to keep it. I'd be up for re-using Slop::UnknownOption
, though
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.
I'd be up for re-using Slop::UnknownOption, though
I think about it and you're right, so I make the changes for this!
I update the documentation for Slop::UnknownOption
also so maybe you want to take a look at it:
Raised when an unknown option is parsed or when trying to fetch an
unexisting option viaSlop::Result#fetch
.
Suppress with thesuppress_errors
config option.
lib/slop/result.rb
Outdated
end | ||
end | ||
|
||
def clean_key(key) |
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.
If you decide to keep this method, please move it to the bottom of the class and mark it as private
. It should only be used internally
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.
Done!
test/result_test.rb
Outdated
assert_equal "lee", @result.fetch("--name") | ||
assert_equal "bar", @result.fetch("long_option") | ||
assert_equal "bar", @result.fetch(:long_option) | ||
assert_equal "bar", @result.fetch("--long-option") |
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.
I think this is a bit over-tested because it's not just testing Result#fetch
, it's also testing Result#get
and others. I think the test examples are good though, but all of them only need one assertion without the duplication
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.
You think it's ok to just leave the following two tests:
assert_equal "lee", @result.fetch("name")
and
e = assert_raises(KeyError) { @result.fetch("unexisting") }
assert_equal "key not found: 'unexisting'", e.message
I'm not pretty sure if remove "returns the default value of an option when a value is not provided"
and "returns nil when an option is not provided and it does not have a default value"
, because they test edge cases, especially the last one.
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.
I'm not pretty sure if remove "returns the default value of an option when a value is not provided" and "returns nil when an option is not provided and it does not have a default value", because they test edge cases, especially the last one.
I think they should be kept too, yes, especially since they catch the nil
issue I mentioned in another comment :)
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.
Cool, I just push those changes :-)
test/result_test.rb
Outdated
assert_equal "bar", @result.fetch("--long-option") | ||
end | ||
|
||
it "raises KeyError when an option does not exists" do |
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.
The description needs updating now :)
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 catch, updated!
This is a fine addition to Slop! Collaboration is happening! Thanks for creating this, together! |
lib/slop/result.rb
Outdated
o = option(flag) | ||
if o.nil? | ||
cleaned_key = clean_key(flag) | ||
raise UnknownOption.new("key not found: '#{cleaned_key}'", "#{cleaned_key}") |
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.
One last nitpick I promise :)
I think the error message should have more detail. "key not found" might be confusing in the context of command line options and flags. After all, what is a key? Perhaps we could just re-use option
like we did for the other UnknownOption
class ("option not found") to clear this up? That might be enough to avoid confusion. What do you think?
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.
Don't worry, I also really want to have this feature as good as possible so don't worry!
If you have any other suggestion I'm open to them :-)
Thanks for your feedback!
@giovannibenussi Thanks for all your work and patience! This looks really great. Please could you squash all of your commits into one? (or into as many as you'd like if you think they're worth retaining for context). Then we'll get it merged. Thanks again! ✨ 💜 |
Sure @leejarvis, I'm gonna make it later because I don't have that much experience squashing commits but I'm gonna learn how to do it! |
@giovannibenussi Great! Give me a shout on Twitter at lee_jarvis or if you're on IRC then irc.freenode.org in the |
@giovannibenussi I'm partial to git-extras' @leejarvis If you interact with the tiny white triangle on the huge green Merge button, you can pick Squash and Merge, but then you won't get any "Merge Commit", which is a difference, of course. Do you prefer to have Merge Commits? Huge screenshot |
use Slop::Result#clean_key in Slop::Result#option fix typo in Slop::Result#[] and Slop::Result#fetch descriptions handle case when Slop::Result#fetch tries to fetch an option that is not provided and does not have a default value raise Slop::UnknownOption when Slop::Result#fetch tries to fetch an unexisting key set Slop::Result#clean_key method as private remove redundant Slop::Result#fetch tests update description of Slop::Result#fetch test when trying to access an unexisting option update error message when an option is not present on Slop::Result#fetch description of Slop::Result#fetch update expected error message on test for Slop::Result#fetch when an option is not present
5882f66
to
0b6d52e
Compare
Thanks for your help guys, I finally can squash the commits with the help of a great tutorial that I find out! Thanks a lot for your help and guidance through this new feature, it was nice to work with both of you! If you have another last-minute change just tell me! Regards! |
@olleolleolle Thanks, I didn't know of that button addition. @giovannibenussi Great work! Thanks again for the contribution, I'll get this merged before the end of the week (@olleolleolle feel free to merge and update the changelog if you'd like) |
No problem @leejarvis ! Thanks to both of you again! :-) |
There, CHANGELOG amended. |
Update ruby-slop to 4.7.0. pkgsr change: Add "USE_LANGUAGES= # none". v4.7.0 (2019-06-29) ------------------- Features: * Add `Slop::Result#fetch`. It returns the value of given option, or raises an error if given option is not present. [#232](leejarvis/slop#232) ([Giovanni Benussi](https://github.com/giovannibenussi)) * Adding a separator without passing any arguments now creates a separator with the empty string. [#238](leejarvis/slop#238) ([Teemu Matilainen](https://github.com/tmatilai)) Bug fixes * Ensure non-string option types have their flags consumed properly [#241] (Sutou Kouhei)
Sometimes I want to raise an error when a given key is not present (for avoid typos for example) so this change implements Slop::Result#fetch allows the following:
Slop::Result#fetch
returns the value associated to a given key asSlop::Result#[]
andSlop::Result#get
but raisesKeyError
if it does not exist.