3

I'm trying to dynamically call instance methods. I found send, call, eval to do that. There are examples of dynamically calling class methods, but I haven't figured out how to make it work for instance methods.

e.g.

module MyModule
  def Foo
    puts "hello"
  end
end

the instance method names can be listed by:

MyModule.instance_methods
#=> [:Foo]

But I can't figure out how to call the method:

MyModule.send("Foo")
#=> NoMethodError: undefined method `Foo' for MyModule:Module

MyModule.method("Foo").call
#=> NameError: undefined method `Foo' for class `Module'

eval 'MyModule.Foo'
#=> NoMethodError: undefined method `Foo' for MyModule:Module

How can I call the instance methods, like Foo, by the method name?

2
  • 1
    Note that eval 'MyModule.Foo' is the same as MyModule.Foo. Commented Apr 20, 2017 at 10:29
  • 4
    It's an instance method. You need an instance. Commented Apr 20, 2017 at 11:08

1 Answer 1

11

Disclaimer: Bad practice and it makes little to no sense:

MyModule.instance_method(:Foo) # #<UnboundMethod: MyModule#Foo>
        .bind(Object)          # #<Method: MyModule#Foo>
        .call                  #=> hello

You can't call an unbound method, thus you have to first bind it to some object.

References:


It would be much easier if you make the method singleton method:

module MyModule
  def self.Foo
    puts "hello"
  end
end

MyModule.Foo
#=> "hello"

Another option is to use module_function (read up on the method's visibility for the including object when using this option):

module MyModule
  def Foo
    puts "hello"
  end
  module_function :Foo
end

MyModule.Foo
#=> "hello"

And yet another one is using extend self:

module MyModule
  def Foo
    puts "hello"
  end

  extend self
end

MyModule.Foo
#=> "hello"

P.S. It is not conventional to use capital letters in method names. It is very rare case in Ruby where it can be used and your case is 100% not the one :)

Sign up to request clarification or add additional context in comments.

6 Comments

Both module_function and extend self are worth to mention here.
Thanks a lot! the singleton method approach works for me!
Without module body editing Class.new.include(MyModule).new.Foo just as ugly but still possible way.
@Ilya you don't have to create a class: Object.new.extend(MyModule).Foo
@Stefan Object.extend(MyModule).Foo is even shorter (despite the pollution caused by it) :)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.