From: Stefano Crocco Date: 2008-08-29T05:22:37+09:00 Subject: Re: Use a string as a method call On Thursday 28 August 2008, Stefano Crocco wrote: > On Thursday 28 August 2008, Chris Bailey wrote: > > I'm trying to come up with an efficient way of using user input as a > > way of calling methods. I'm unhappy with the way that I am doing it > > because it isn't very flexible. This is what I'm doing now. > > > > input = gets.downcase.chomp > > > > if input == foo > > do_foo() > > elsif input == bar > > do_bar() > > else > > puts "That isn't a command!" > > end > > > > What I would like to do is more like so. > > > > commands = { > > 'foo' => do_foo(), > > 'bar' => do_bar() > > } > > > > I then would like to search the commands hash for a key that matches the > > player input and execute the method associated with that key. What I've > > noticed is that upon initialization of the hash the value becomes equal > > to the result of the method but that is not what I want. If I store the > > value as a string ie "do_foo()" would I be able to parse that string and > > execute it as a method? And if so, how would that be done? > > You can do something like this: > > method_name = gets.downcase.chomp > send method_name > > send is a method which takes as a first argument a method name (as a string > or symbol) and calls that method on its receiver, passing all the remaining > arguments to it (see ri Object#send for a better explaination). To better > handle the possibility the user inserts a wrong string, you can rescue the > NoMethodError exception: > > method_name = gets.downcase.chomp > begin > send method_name > rescue NoMethodError > puts "#{method_name} is not a valid command" > end > > If you want to restrict the methods the user can call, store them in an > array and check whether the string he entered is there before calling send: > > commands = %w[foo bar] > method_name = gets.downcase.chomp > if commands.include? method_name then send method_name > else puts "#{method_name} is not a valid command" > end > > I hope this helps > > Stefano Of course, with this approach, you'll need to change the names of your methods to foo and bar, or to change the definition of method_name to something like this: method_name = "do_#{gets.downcase.chomp}" Stefano