FiveRuns Blog

On Rails production performance and monitoring

Posts
5 comments

One Year With Ruby and Sometimes Still a Newbie

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

Bookmark and Share
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
end
Dr Nic Dr Nic said:

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

Travis Travis said:

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.

Eric Eric said:

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.

Eric Eric said:

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.

George George said:

on June 26, 2008 at 04:10 PM

Contribute

Continue the conversation and share your thoughts. A name is required. Your e-mail address will not be displayed on the site. Textile formatting may be used in your comments (but will not be rendered in the live comment preview).

→ Posted by You on August 07, 2008 at 06:37 PM

Flickr

FiveRuns tagged photos on Flickr.

  • IMG_4686
  • IMG_4687
  • FiveRuns Booth
  • FiveRuns RailsConf 2008
  • IMG_4692
  • FiveRuns RailsConf 2008
  • FiveRuns RailsConf 2008
  • FiveRuns Booth

See more FiveRuns tagged photos…

Other Categories

Entries are also organized under the following general topic categories.