Reputation: 71101
How can I do what they are talking about here, but in Ruby?
How would you do the function on an object? and how would you do a global function (see jetxee's answer on the post mentioned)?
EXAMPLE CODE:
event_name = "load"
def load()
puts "load() function was executed."
end
def row_changed()
puts "row_changed() function was executed."
end
#something here to see that event_name = "load" and run load()
UPDATE: How do you get to the global methods? or my global functions?
I tried this additional line
puts methods
and load and row_change where not listed.
Upvotes: 183
Views: 118391
Reputation: 4274
To call functions directly on an object
a = [2, 2, 3]
a.send("length")
# or
a.public_send("length")
which returns 3 as expected
or for a module function
FileUtils.send('pwd')
# or
FileUtils.public_send(:pwd)
and a locally defined method
def load()
puts "load() function was executed."
end
send('load')
# or
public_send('load')
Documentation:
Upvotes: 270
Reputation: 54756
send
/ call
/ eval
- and their BenchmarksTypical invocation (for reference):
s= "hi man"
s.length #=> 6
send
s.send(:length) #=> 6
call
method_object = s.method(:length)
p method_object.call #=> 6
eval
eval "s.length" #=> 6
require "benchmark"
test = "hi man"
m = test.method(:length)
n = 100000
Benchmark.bmbm {|x|
x.report("call") { n.times { m.call } }
x.report("send") { n.times { test.send(:length) } }
x.report("eval") { n.times { eval "test.length" } }
}
...as you can see, instantiating a method object is the fastest dynamic way in calling a method, also notice how slow using eval is.
#######################################
##### The results
#######################################
#Rehearsal ----------------------------------------
#call 0.050000 0.020000 0.070000 ( 0.077915)
#send 0.080000 0.000000 0.080000 ( 0.086071)
#eval 0.360000 0.040000 0.400000 ( 0.405647)
#------------------------------- total: 0.550000sec
# user system total real
#call 0.050000 0.020000 0.070000 ( 0.072041)
#send 0.070000 0.000000 0.070000 ( 0.077674)
#eval 0.370000 0.020000 0.390000 ( 0.399442)
Credit goes to this blog post which elaborates a bit more on the three methods and also shows how to check if the methods exist.
Upvotes: 45
Reputation: 96767
Use this:
> a = "my_string"
> meth = a.method("size")
> meth.call() # call the size method
=> 9
Simple, right?
As for the global, I think the Ruby way would be to search it using the methods
method.
Upvotes: 34
Reputation: 45321
Personally I would setup a hash to function references and then use the string as an index to the hash. You then call the function reference with it's parameters. This has the advantage of not allowing the wrong string to call something you don't want to call. The other way is to basically eval
the string. Do not do this.
PS don't be lazy and actually type out your whole question, instead of linking to something.
Upvotes: 3