Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call methods dynamically based on their name? [duplicate]

How can I call a method dynamically when its name is contained in a string variable? For example:

class MyClass   def foo; end   def bar; end end  obj = MyClass.new str = get_data_from_user  # e.g. `gets`, `params`, DB access, etc. str  #=> "foo" # somehow call `foo` on `obj` using the value in `str`. 

How can I do this? Is doing so a security risk?

like image 771
user502052 Avatar asked Mar 18 '11 08:03

user502052


People also ask

How do you call a method dynamically?

Using user data to call any method via send could leave room open for users to execute any method they want. send is often used to call method names dynamically—but make sure the input values are trusted and can't be manipulated by users. Golden rule is never trust any input that comes from the user.

How do you call a method dynamically in Ruby?

Fortunately, Ruby's metaprogramming feature allows us to call methods dynamically by just passing the method name into public_send(method_name) or send(method_name) .


1 Answers

What you want to do is called dynamic dispatch. It’s very easy in Ruby, just use public_send:

method_name = 'foobar' obj.public_send(method_name) if obj.respond_to? method_name 

If the method is private/protected, use send instead, but prefer public_send.

This is a potential security risk if the value of method_name comes from the user. To prevent vulnerabilities, you should validate which methods can be actually called. For example:

if obj.respond_to?(method_name) && %w[foo bar].include?(method_name)   obj.send(method_name) end 
like image 191
David Avatar answered Sep 28 '22 01:09

David