Ross Bamford wrote:
> On Sat, 2006-03-25 at 14:03 +0900, Eli Bendersky 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)