Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ruby - how to dynamically call instance method in a module

Tags:

ruby

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?

like image 791
jerry Avatar asked Jul 04 '26 19:07

jerry


1 Answers

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:

  • Module#instance_method

  • UnboundMethod#bind

  • Method#call


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 :)

like image 80
Andrey Deineko Avatar answered Jul 07 '26 07:07

Andrey Deineko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!