Left SE On 10_6_19
Left SE On 10_6_19

Reputation: 768

What is the point of the "method" method in Ruby?

In Ruby, there is the "method" method, which creates a method object that you can then treat as a Proc. This is useful if you wish to do metaprogramming:

def foobar(method_as_a_string)
   2.method(method_as_a_string).call(2)
end

foobar("+")
=> 4

foobar("-")
=> 0

However, normally, if you want to do such meta-programming, you would use send instead of method...

def foobar(method_as_a_string)
   2.send(method_as_a_string, 2)
end

foobar("+")
=> 4

foobar("-")
=> 0

What is the point of the "method" method then in Ruby?

Upvotes: 10

Views: 2628

Answers (4)

max pleaner
max pleaner

Reputation: 26758

You can pass a method result to a block, and it will call the method passing the iteratee as arguments.

For example, this wouldn't work:

[1,2,3].each(&:puts)

because it's calling 1.puts, 2.puts, etc. But this would:

[1,2,3].each(&method(:puts))

Another example:

arr, result = [1,2,3], []
arr.each &result.method(:push)
result # => [1,2,3]

Another useful thing is using it to find the source location of a method:

Someclass.method(:some_method).source_location
# => this will give you the file & line where it's defined

This is a very helpful trick when you're working with gems and want to quickly glance at their source code

Upvotes: 12

coreyward
coreyward

Reputation: 80041

A Method object provides for all sorts of introspection and metaprogramming, including:

  1. Getting the arity or parameters for the method
  2. Getting the source code location for the method, which is useful in debugging or when writing tools that interact or inspect the source of the application that's running
  3. Getting the receiver of the method

How and what you use those powers for is up to you.


For Cary, below:

"cat".method(:count).receiver
# => "cat"

Upvotes: 7

Eric Duminil
Eric Duminil

Reputation: 54223

I often use it when looking for documentation.

As an example :

[1, 2, 3, 4, 5, 6].slice_after{|x| x.odd? }

The receiver is an Array, but there's no slice_after in the Array doc.

It means slice_after is defined somewhere in :

Array.ancestors
#=> [Array, Enumerable, Object, Kernel, BasicObject]

Instead of looking at the documentation of those classes :

[1, 2, 3, 4, 5, 6].method(:slice_after)
#=> #<Method: Array(Enumerable)#slice_after>

So the method is defined in Enumerable, and made available to Array objects.

Upvotes: 3

Mike
Mike

Reputation: 123

There are other aspects of metaprogramming than just working with methods directly. I wrote some code recently that needed to identify what class a method was actually defined in.

Here's a simple example:

class Foo
  def bar
    puts "bar"
  end
end

# to get the owner of bar method here
Foo.new.method(:bar).owner

I was working with a scenario where many classes were extending a single class, and in that single class I needed to know where a method was defined for tracking purposes. I wrote this in a Rails application, inside a before_filter for every method.

This has been the only time I've needed #method directly.

Upvotes: 4

Related Questions