如何在方法内部猴子对红宝石类进行修补 [英] How to monkey patch a ruby class inside a method

查看:91
本文介绍了如何在方法内部猴子对红宝石类进行修补的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法在方法正文中使用猴子补丁类.

I am unable to monkey patch a class inside a method body.

在方法定义中, 我正在尝试通过两种方式使用类:

Within a method definition, I am trying to use a class in two ways:

1]创建一个实例,并在我正在使用的类中使用方法的原始定义

1] Create an instance and use the orignal definition of a method in the class I am using

2]猴子修补(pverride)类中的一个方法,现在使用具有新方法定义的实例.

2] Monkey patch (pverride) a method in the class and now use an instance with the new method definition.

基本上,我会在程序中同时使用上述两个类的实例.

Basically I would be using both of the above instances of a class in my program.

挑战在于初始化过程中将调用我覆盖的方法,因此在创建类的实例之前必须覆盖它.

The challenge is the method I am overriding gets called during initialization so I have to override it before I create the instance of the class.

这是一个小模型:

class A

  def initialize
   do_something
  end

  def do something
     #implementation
  end

end

现在,我想在相同的方法中使用A两次,但是一次要使用do_something的修改版本 这就是我要尝试的方式:

Now , I want to use A in the same method twice , but once by using a modified version of do_something This is how I am trying to do it:

def my_method

  orig_instance = A.new

  #patch the class
  Class A          # ERROR: CLASS DEF IN METHOD BODY
   class << self
     alias_method :old_do_something, :do_something

     def self.do_something
        # new implementation
     end
  end

  new_instance = A.new

  #restore method
   class << self
     alias_method :do_something,:old_do_something

     def self.do_something
        # new implementation
     end
  end        



end # end of method

我得到了(错误:方法主体中的类定义),在这里我试图猴子修补类,因为我试图在方法内部更改类.

I get the (ERROR: CLASS DEF IN METHOD BODY) where I try to monkey patch the class, since I am trying to change the class inside of a method.

如何在方法中实现猴子修补类?

How do I achieve monkey patching the class in a method ?

谢谢

推荐答案

您可以使用Module#class_evalModule#instance_eval和其他一些元编程实用程序来代替使用class Clazz; blabla; end重新打开Clazz并对其进行猴子修补. /方法可以完成相同的技巧.而且由于这些方法接受的那个块不会创建新的绑定范围,因此在元编程实践中更加方便.

Instead of using class Clazz; blabla; end to reopen Clazz and monkey patch it, you can use Module#class_eval, Module#instance_eval and some other meta-programming utilities/methods to do the same trick. And because that block accepted by these methods doesn't create new binding scopes, it is more convenient in meta-programming practice.

def my_method
  puts ">> creating orig_instance"
  orig_instance = A.new

  puts ">> dump orig_instance"
  orig_instance.do_something

  new_do_something = lambda do
    puts "Modified A#do_something"
  end

  # monkey patch class A so that the modified version of do_something get called
  # during initialization of new_instance
  A.class_eval do
    alias_method :old_do_something, :do_something
    define_method :do_something, new_do_something
  end

  puts ">> creating new_instance"
  new_instance = A.new

  puts ">> dump before do_something gets restored"
  new_instance.do_something
  orig_instance.do_something

  # add singleton method for the special instance
  # so that the instance always calls the modified do_something
  new_instance_singleton = class << new_instance; self end
  new_instance_singleton.send :define_method, :do_something, new_do_something

  # restore the modified do_something
  # so that orig_instance and all other instances (except new_instance) have the original definition
  A.class_eval do
    alias_method :do_something, :old_do_something
  end
  puts ">> dump for final result"
  new_instance.do_something
  orig_instance.do_something
end

以下是my_method调用的输出:

>> creating orig_instance
Original A#do_something
>> dump orig_instance
Original A#do_something
>> creating new_instance
Modified A#do_something
>> dump before do_something gets restored
Modified A#do_something
Modified A#do_something
>> dump for final result
Modified A#do_something
Original A#do_something

这篇关于如何在方法内部猴子对红宝石类进行修补的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆