Ross Bamford
3/25/2006 10:03:00 AM
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.
--
Ross Bamford - rosco@roscopeco.REMOVE.co.uk