Have you ever wanted to pass a method to a function that only takes a block? Or figure out which of your object’s superclasses broke the method you’re trying to call?

Those things are easy to do with the method method. Use it well, and you can learn about your dependencies, save yourself hours of debugging, and get your code to the places it needs to be.

Methods as easy as lambdas

Lots of Ruby methods take blocks or lambdas. But you can’t directly pass a method to another method, the way you would with a lambda. You have to use method first:

irb(main):001:0> sin_method = Math . method ( :sin ) => #< Method : Math . sin > irb(main):002:0> ( 1 .. 10 ). map ( & sin_method ) => [ 0.8414709848078965 , 0.9092974268256817 , 0.1411200080598672 , - 0.7568024953079282 , - 0.9589242746631385 , - 0.27941549819892586 , 0.6569865987187891 , 0.9893582466233818 , 0.4121184852417566 , - 0.5440211108893699 ]

So, what’s happening here?

The first line turns the method Math.sin into a Method object. Just like lambdas, `Method` objects respond to `call`. Method objects respond to to_proc (Thanks, Benoit). So they can be used in the same places you’d use a lambda:

irb(main):004:0> sin_method = -> ( x ) { Math . sin ( x ) } => #<Proc:0x007fe9f90a9bd8@(irb):4 (lambda)> irb(main):005:0> ( 1 .. 10 ). map ( & sin_method ) => [ 0.8414709848078965 , 0.9092974268256817 , 0.1411200080598672 , - 0.7568024953079282 , - 0.9589242746631385 , - 0.27941549819892586 , 0.6569865987187891 , 0.9893582466233818 , 0.4121184852417566 , - 0.5440211108893699 ]

Take a look at the first line again. This code, using a lambda, works the same way as the earlier code, using method .

Depending on how you’ve written your code, getting ahold of a Method object can be a lot easier than wrapping it in a lambda. So when you need a lambda and all you have is a method, remember the method method.

Where did that method come from?

You just called a method on your object, and it does something you didn’t expect. Maybe someone overrode it or monkey-patched it. How do you figure this out?

You could dig through the source code for a few hours. But Method has two methods that can speed things up.

To figure out which class defined the method you’re calling, use owner :

irb(main):003:0> Task . new . method ( :valid? ). owner => ActiveRecord :: Validations

When you want to go a little deeper and figure out exactly where the method was defined, use source_location :

irb(main):004:0> Task . new . method ( :valid? ). source_location => [ "/usr/local/lib/ruby/gems/2.1.0/gems/activerecord-4.2.0.beta2/lib/active_record/validations.rb" , 55 ]

source_location returns an array. The first element is the path to the file where the method was defined, and the second element is the line number. With those, you know exactly where to look next.

Reading the source (without having to dig)

Once you can figure out where a method was defined, you might want to see how it’s defined.

Method can’t do that by itself. But if you install the method_source gem, you can see the source code for many methods right from your console:

irb(main):002:0> puts Task . new . method ( :valid? ). source def valid?(context = nil) context ||= (new_record? ? :create : :update) output = super(context) errors.empty? && output end => nil

You can even see the comments:

irb(main):003:0> puts Task . new . method ( :valid? ). comment # Runs all the validations within the specified context. Returns +true+ if # no errors are found, +false+ otherwise. # # Aliased as validate. # # If the argument is +false+ (default is +nil+), the context is set to <tt>:create</tt> if # <tt>new_record?</tt> is +true+, and to <tt>:update</tt> if it is not. # # Validations with no <tt>:on</tt> option will run no matter the context. Validations with # some <tt>:on</tt> option will only run in the specified context. => nil

Pretty awesome, right? Your documentation is right in the console!

Introspection is awesome