Verifying keyword arguments


#1

Hello all,

I’m now writing my first real Ruby module, and on the second function I
already run into a pattern that seems to be very common.
I like using keyword arguments for methods, as follows:

def method(args)

end

And then call:

method(:arg1 => value1, :arg2 => value2)

And so on.
Now, often some arguments are compulsory, so I wrote the following code
to verify it:

def method(args)
[:username, :password, :url].each do |arg|
raise(ArgumentError, “Argument :#{arg} is compulsory” unless
args.has_key?(arg)
end


end

I have two questions:

  1. Is this the right/idiomatic/best way to achieve what I’m attempting
    ?
  2. Is there a library that encapsulates this capability, or is everyone
    writing one of his own ? Because if I don’t find any, I surely will
    write one… It should be enough saying:

verify_args(:username, :password, :url)

Instead of the .each do iteration everywhere

Eli


#2

On Fri, 24 Mar 2006, Eli B. wrote:

And then call:
args.has_key?(arg)
write one… It should be enough saying:

verify_args(:username, :password, :url)

Instead of the .each do iteration everywhere

Eli

http://codeforpeople.com/lib/ruby/
http://codeforpeople.com/lib/ruby/parseargs/parseargs-0.3.0/README

regards.

-a


#3

Eli B. wrote:

And then call:
args.has_key?(arg)
write one… It should be enough saying:

verify_args(:username, :password, :url)

Instead of the .each do iteration everywhere

Eli

Is this topic of no interest to anyone but me ? :-/


#4

On Sat, 2006-03-25 at 14:03 +0900, Eli B. wrote:

raise(ArgumentError, "Argument :#{arg} is compulsory" unless

args.has_key?(arg)
end


end

I have two questions:

  1. Is this the right/idiomatic/best way to achieve what I’m attempting
    ?

It works, and strikes me as more compact and elegant than a simple
‘raise unless args[:username] && args[:password] && …’.

  1. Is there a library that encapsulates this capability, or is everyone
    writing one of his own ? Because if I don’t find any, I surely will
    write one… It should be enough saying:

verify_args(:username, :password, :url)

Instead of the .each do iteration everywhere

Not sure about libraries (though I’m sure they are out there, check RAA
and Rubyforge) but here’s a little trick I’ve used before:

args = { :one => ‘two’, :three => ‘four’ }

=> {:three=>“four”, :one=>“two”}

h = Hash.new { |h,k| raise ArgumentError, “#{k}” }.merge(args)

=> {:three=>“four”, :one=>“two”}

h[:one]

=> “two”

h[:three]

=> “four”

h[:two]
ArgumentError: two
from (irb):5
from (irb):11

This way, you never actually check the arguments explicitly, but you’ll
be told if your method uses one that wasn’t passed. Obviously for
optional arguments you go to the original hash.


#5

Ross B. wrote:

end
[:username, :password, :url].each do |arg|

h[:one]
This way, you never actually check the arguments explicitly, but you’ll
be told if your method uses one that wasn’t passed. Obviously for
optional arguments you go to the original hash.

This is a nice trick that can be used to handle optional keyword
variables with default values, and indeed it helps detect unwanted
variables.
I think it can be somehow combined with the method I presented - the
aim of which is to detect if any compulsory argument wasn’t passed in.
After all, there are arguments for which a default value is
meaningless.

Eli – (http://eliben.blogspot.com)


#6

Ross B. wrote:

=> “two”

be told if your method uses one that wasn’t passed. Obviously for
optional arguments you go to the original hash.

What about using rescue for optional arguments? It might be slower
though.


#7

Joel VanderWerf wrote:

This way, you never actually check the arguments explicitly, but you’ll
be told if your method uses one that wasn’t passed. Obviously for
optional arguments you go to the original hash.

What about using rescue for optional arguments? It might be slower though.

What do you mean ? Can you provide an example ?


#8

Eli B. wrote:

=> {:three=>“four”, :one=>“two”}

    from (irb):11

This way, you never actually check the arguments explicitly, but you’ll
be told if your method uses one that wasn’t passed. Obviously for
optional arguments you go to the original hash.

What about using rescue for optional arguments? It might be slower though.

What do you mean ? Can you provide an example ?

args = { :one => ‘two’, :three => ‘four’ }

=> {:three=>“four”, :one=>“two”}

h = Hash.new { |h,k| raise ArgumentError, “#{k}” }.merge(args)

=> {:three=>“four”, :one=>“two”}

h[:one]

=> “two”

h[:three]

=> “four”

v = h[:two] rescue “this string is the default for ‘two’”
p v

=> “this string is the default for ‘two’”