Ruby metaprogramming: unable to send method to module

For example, I have the following custom class and module:

module SimpleModule
  def hello_world
    puts 'i am a SimpleModule method'
  end

  def self.class_hello_world
    puts 'i am a SimpleModule class method'
  end
end

class SimpleClass
  def hello_world
    puts 'i am SimpleClass method'
  end

  def self.class_hello_world
    puts 'i am a SimpleClass class method'
  end
end

I tried calling these methods inside the class and module using the method send

SimpleClass.send(class_hello_world)  # work
SimpleClass.new.send(hello_world)    # work
SimpleModule.send(class_hello_world) # work
SimpleModule.new.send(hello_world)   # not work
SimpleModule.send(hello_world)       # not work

In other words, I do not know how to call hello_worldout SimpleModule. This is possible if this method is defined previously.

I need to do this because I want to implement "custom-include": include all methods from the module in another class.

Please tell me how to do this.

+1
source share
3 answers

Five operators

( , ). , send , .

SimpleModule.send("class_hello_world")
  # i am a SimpleModule class method

, . , Math, .

SimpleClass.send(:class_hello_world)
  # i am a SimpleClass class method

, , . class_hello_world .

SimpleClass.new.send(:hello_world)
  # i am SimpleClass method

.

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

hello_world.

SimpleModule.new.send(hello_world)
  #=> NoMethodError: undefined method `new' for SimpleModule:Module

.

include vs prepend

,

SimpleClass.include SimpleModule
  #=> SimpleClass
SimpleClass.new.hello_world
  # i am SimpleClass method

SimpleClass ' hello_world . SimpleClass.

SimpleClass.ancestors
  #=> [SimpleClass, SimpleModule, Object, Kernel, BasicObject]

Ruby hello_world SimpleClass - - SimpleModule.

, , Module # prepend SimpleModule#hello_world SimpleClass#hello_world.

SimpleClass.prepend SimpleModule
  #=> SimpleClass
SimpleClass.new.hello_world
  # i am a SimpleModule method
SimpleClass.ancestors
  #=> [SimpleModule, SimpleClass, Object, Kernel, BasicObject]

, . SimpleModule ( ) . UnboundMethod # bind SimpleClass, call send.

sc = SimpleClass.new
  #=> #<SimpleClass:0x007fcbc2046010> 
um = SimpleModule.instance_method(:hello_world)
  #=> #<UnboundMethod: SimpleModule#hello_world> 
bm = um.bind(sc)
  #=> #<Method: SimpleModule#hello_world> 
bm.call
  #=> i am a SimpleModule method
sc.send(:hello_world)
  #=> i am a SimpleModule method
+5

, . , mixin. "mixins" .

docs

Edit:

, - :

module SimpleModule
  def hello_world
    p 'hello world'
  end
end

class Example
  include SimpleModule
end

Example.new.send(:hello_world)

mixin .

+2

, , include.

Module.append_features

, Ruby append_features , . Ruby default , mod, mod . . β„–.

, , , include .

And since you're adventurous, you might like to read the Ruby source code to see how exactly this is implemented internally. See https://github.com/ruby/ruby...class.c#L853:L934

+2
source

Source: https://habr.com/ru/post/1668806/


All Articles