I wrote a block of code the other day that had to do with authentication. The use case is that sometimes users authenticate by email and password, and occasionally (in the case of a forgotten password or first login) users can authenticate with a token that is sent via email allowing them to change their password.
So this is what I wrote:
def authenticate(email, password) ... end def authenticate(token) ... end
and then I tried logging in with an email and password. Oops! The Ruby veterans are out there laughing at me. There is no method overloading in Ruby.
I guess my initial reaction was disbelief. Coming from .NET, overloading methods is something you do just about every day. On one hand, it makes perfect sense not to have the feature in Ruby because method overloading and typing of method arguments are very closely related, but on the the other hand, I am only talking about a variable number of arguments, which has nothing to do with typing.
Here is what I ended up with:
def authenticate(*args)
if args.size == 1
...
else
...
end
end
It’s not the prettiest of solutions. Here is another way, where args is a hash:
def authenticate(args)
if args.has_key?(:token)
....
else
...
end
end
#usage
authenticate(:token => 'zA3sDV')
authenticate(:email => 'foo@asdf.com', :password => 'password')
I am definitely thinking that the second way is cleaner. I better get going, I have some code to refactor ;-)















Continued Discussion
5 responses to this entry
Perhaps it would be lovely and readable for your pseudo-overridden authenticate method directly called one of two specific implementations:
def authenticate(args) if args.has_key?(:token) authenticate_with_token(args.first) else authenticate_with_username_password(args[0..1]) end endon May 06, 2008 at 06:37 PM
Since the caller knows what arguments it will be authenticating with, why not just call authenticate_with_token or authenticate_with_username_password directly? Encapsulating the behavior into a single method only adds a layer of complexity.
on May 07, 2008 at 10:09 AM
Hey Dr Nic,
That’s pretty much what my ”...”’s above do. The username/password auth is a method. The token auth is a one-liner, so it’s inline in authenticate.
Thanks for the comment.
on May 07, 2008 at 10:27 AM
Travis,
You have a good point. I think that the main reason why this ‘problem’ occurred in the first place is because my thinking was .NET-centric.
Without method overloading, it’s easier to write two different methods that explicitly state what to call with.
on May 07, 2008 at 10:33 AM
Or if you write crappy code like me, you could do
def authenticate(email, password = nil) if password.blank? assume_email_is_a_token etc.
on June 26, 2008 at 04:10 PM