Ruby, Ruby on Rails

Wherefore Art Thou Method?

I’ve been learning me some iOS lately, the most striking feature is the IDE, coming from Ruby and my trusty text editor, IDEs were kind of a shock. It kinda felt like someone always looking over my shoulder. Constantly pointing out what I did wrong, sometimes while in the middle of typing.

After a while I grew quite fond of Xcode, I like how you could option-click a method and see what it was all about, or at least where it was defined.

Ruby doesn’t have anything like that, at least not in the text editor. And what with its plethora of gems, its kinda hard sometimes to find where a method comes from.

I encountered a something like this earlier this week when I was trying to understand some code that was written by another developer.

The app was using  Clearance, which is a pretty nifty authentication gem. So obviously an authentication gem would need a method called “authenticate” right?  I got confused though when I saw it was used like this:

 @user = authenticate(params)

However, when I tried to use it like this:

 User.authenticate(params)

I got a

ArgumentError: wrong number of arguments (given 1, expected 2)

That was weird, looking into the Clearance gem source code, I found this in authentication.rb :

  def authenticate(params)
        Clearance.configuration.user_model.authenticate(
          params[:session][:email], params[:session][:password]
        )
      end

So obviously it accepts one argument right? Maybe another authenticate method was defined somewhere else. After hours of intense research and/or googling around for a bit, I found a method in Ruby called source_location

What this does is it tells you where a method is defined. So running this line in the rails console :

 User.method(:authenticate).source_location

will return this line:

 ["/Users/farisroslan/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/clearance-1.10.1/lib/clearance/user.rb", 19]

So it turns that there was another authenticate method defined in user.rb!

 def authenticate(email, password)
        if user = find_by_normalized_email(email)
          if password.present? && user.authenticated?(password)
            return user
          end
        end
      end

So now modifying my authenticate method for User so it looks like this:

 User.authenticate(session_params[:email],session_params[:password])

It worked well.

Now in hindsight, perhaps searching “authenticate” in the Clearance repo would have probably be quicker.Still, it should be useful if the other method is in another gem or library.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s