Reputation: 768
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
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
Reputation: 80041
A Method
object provides for all sorts of introspection and metaprogramming, including:
How and what you use those powers for is up to you.
For Cary, below:
"cat".method(:count).receiver
# => "cat"
Upvotes: 7
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
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