4

I cant seem to follow this answer but maybe it's different from what I'm trying to achieve.

I have a string, that string can be different at time, I need to convert that string into a defined method name:

action = "get_name"

# The method
def get_name
  puts "James"
end

# Calling the method
action # => undefined method `action' for main:Object

action can be any of my defined methods and the names are in a string format. Could I say action.to_method, you get what I mean ;)

I dont think I could say action.to_sym?

Community
  • 1
  • 1
Sylar
  • 11,422
  • 25
  • 93
  • 166

1 Answers1

4
method(action).call

or

public_send(action)

Example:

method(action).call
#=> James
public_send(action)
#=> James

Be aware, though, that none of the above cares about the context, where was method originally defined, so both will call it in the context of the current object.

Andrey Deineko
  • 51,333
  • 10
  • 112
  • 145
  • Hi, would that work even if I have params ie: `action(a,b)` – Sylar Feb 25 '17 at 14:18
  • @Sylar no, in that case it will not work. because, for example, with `public_send` it sould look like `public_send(action, a, b)`, where `a` and `b` are arguments. – Andrey Deineko Feb 25 '17 at 14:22
  • `public_send()` is best. Thank you! – Sylar Feb 25 '17 at 14:23
  • @Sylar with such case `eval` would do: `eval("action(1,2)")`, where `1` and `2` are actual arguments. But as we all know, `eval` is evil, ***especially*** when you are evaluating something from incoming params, so don't even think about it!) – Andrey Deineko Feb 25 '17 at 14:24
  • So what's the safest? `public_send`? – Sylar Feb 25 '17 at 14:25
  • @Sylar absolutely, `public_send` does care even about the scope of the defined method, so if you try to call `private` method with `public_send` it will fail, whereas with `send` it will call it anyway. So for clean interface `public_send` is safest you can get. – Andrey Deineko Feb 25 '17 at 14:26
  • No problem. Thanks! – Sylar Feb 25 '17 at 14:29
  • Just be aware that `public_send` is still dangerous with parameters provided by the user, because `send` is itself a public method. So if the user can control additional parameters, they can call pretty much any method on the object. And since any descendant of `Object` has dangerous private methods like `eval` and `exit!` by default, you can get into a lot of trouble. The only safe thing to do with user-provided parameters is to compare them against a list of explicitly allowed methods. – Max Feb 25 '17 at 15:00
  • @Sylar yea, what Max says, white-list of allowed methods is really the only safe way to "let" user do that. Thx Max for comment! – Andrey Deineko Feb 25 '17 at 15:01
  • @Max Thanks. No user calls any method, only functions. – Sylar Feb 25 '17 at 15:10