'Modify mixin method extended from a 1st module with a included second module in Ruby

Context

I'm using a software implemented in Ruby, this software allows to build "plugin" modules to add custom behaviors.

My problem

A function in the core software undoes actions done by my plugin.

In the example bellow (playground), the run is the simplification of the function modifying my actions done by plugin_run:

#################
# No controle of file here, core
module ModuleBase
  def self.create
    Module.new do
      include ModuleBase
      add_method
    end
  end
  
  def self.included(klass)
    klass.extend(ClassMethods)
  end

  module ClassMethods
    def add_method
      define_method(:test_m) {puts "test_m from Base"}
      define_method(:another_m) { puts "other" }
    end
  end
 
end

class NotMyClass
  def initialize
    extend ModuleBase.create
  end
  def load
    self.class.include(ModulePlugin.fix)
    #include ModulePlugin.fix
  end
  
  def run
    puts "run from class"
    plugin_run if defined?(plugin_run)
    test_m
  end
  
end

########
# I have the control here, plugin

module ModulePlugin
  
  def self.fix
    my_mod = Module.new do
      include ModulePlugin
      fix_method
    end
  end
  
  def self.included(klass)
    klass.extend(ClassMethods)
    klass.extend(self)
  end
  
  def plugin_run
    puts "plugin run"
  end
  
  def test_m
    puts 'test_m modified !'
  end

  
  module ClassMethods
    
    def fix_method
      define_method(:test_m) {puts "test_m modified try !"}
      define_method(:test2_m) {puts "not what i want" }
    end
    
  end
  
end


##################
# No more control

u = NotMyClass.new

# internal preparation stuff

u.load
u.run

# debug
puts
puts "# Debug"
p u.methods
p u.method(:test_m)
p u.method(:test2_m)

Result in:

run from class
plugin run
test_m from Base #=> 'test_m modified !' is wanted here

# Debug
[:test_m, :another_m, :load, :run, :test2_m, :plugin_run, ...
#<Method: NotMyClass(#<Module:0x04329638>)#test_m() eval:17> # module id is different than the module id of test2_m
#<Method: NotMyClass(#<Module:0x04329408>)#test2_m() eval:71>

Question

How can I modify the test_m behavior by controlling only the code in the plugin?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source