Verifying keyword arguments

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

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

regards.

-a

···

On Fri, 24 Mar 2006, Eli Bendersky wrote:

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

--
share your knowledge. it's a way to achieve immortality.
- h.h. the 14th dali lama

Eli Bendersky wrote:

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

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

Eli Bendersky wrote:
> 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
> ?

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

> 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
>

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.

···

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

--
Ross Bamford - rosco@roscopeco.REMOVE.co.uk

Ross Bamford wrote:

> Eli Bendersky wrote:
> > 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
> > ?

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

> > 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
> >

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.

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)

···

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

Ross Bamford wrote:
...

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.

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

···

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Joel VanderWerf wrote:

Ross Bamford wrote:
..
> 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.
>

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

What do you mean ? Can you provide an example ?

Eli Bendersky wrote:

Joel VanderWerf wrote:

Ross Bamford wrote:
..

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.

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'"

···

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407