As far as I am aware there are three ways to dynamically call a method in Ruby:
Method 1:
s = SomeObject.new
method = s.method(:dynamic_method)
method.call
Method 2:
s = SomeObject.new
s.send(:dynamic_method)
Method 3:
s = SomeObject.new
eval "s.dynamic_method"
By benchmarking them I have established that Method 1 is by far the fastest, Method 2 is slower, and Method 3 is by far the slowest.
I have also found that .call
and .send
both allow calling private methods, while eval
does not.
So my question is: is there any reason to ever use .send
or eval
? Why would you not always just use the fastest method? What other differences do these methods of calling dynamic methods have?
is there any reason to ever use
send
?
call
needs a method object, send
doesn't:
class Foo
def method_missing(name)
"#{name} called"
end
end
Foo.new.send(:bar) #=> "bar called"
Foo.new.method(:bar).call #=> undefined method `bar' for class `Foo' (NameError)
is there any reason to ever use
eval
?
eval
evaluates arbitrary expressions, it's not just for calling a method.
Regarding benchmarks, send
seems to be faster than method
+ call
:
require 'benchmark'
class Foo
def bar; end
end
Benchmark.bm(4) do |b|
b.report("send") { 1_000_000.times { Foo.new.send(:bar) } }
b.report("call") { 1_000_000.times { Foo.new.method(:bar).call } }
end
Result:
user system total real
send 0.210000 0.000000 0.210000 ( 0.215181)
call 0.740000 0.000000 0.740000 ( 0.739262)