如何为特定方法启用猴子补丁? [英] How to enable monkey patch for specific method?

查看:58
本文介绍了如何为特定方法启用猴子补丁?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 gem,出于某种原因,它的一个方法需要修补才能被我的一些代码使用.

I am using a gem, for some reason, one of its method needs to be patched before it can be used by some of my code.

问题就在这里,比如说,我怎样才能为我的一些代码启用这个补丁.对于类中的某些方法,我需要启用此补丁;有些我想禁用这个补丁.

The problem is here, how can I enable this patch just for some of my code, say. for some method inside a class, I need to enable this patch; some I want to disable this patch.

如何做到这一点?

class FromGem
    def BlahBlah
       #patch here
    end
end

class A 
   def Test1
         #need patch
   end 

   def Test2
         # don't need patch
   end
end

推荐答案

这就是 Refinements 的用途.

This is what Refinements are for.

比如说,我们有以下第三方代码:

Say, we have the following third-party code:

class FromGem
  def say_hello
    'Hello'
  end
end

FromGem.new.say_hello
# => 'Hello'

我们想将其扩展为Hello World",我们会这样做:

And we want to extend it to say "Hello World" instead, we'd do something like this:

module ExtendFromGem
  def say_hello
    super + ' World'
  end
end

class FromGem
  prepend ExtendFromGem
end

FromGem.new.say_hello
# => 'Hello World'

这只是扩展行为的标准方式,当然,这仍然是全局的.如果我们想限制我们的猴子补丁的范围,我们将需要使用 Refinements:

That's just the standard way of extending behavior, of course, this is still global. If we want to restrict the scope of our monkey-patch, we will need to use Refinements:

module ExtendedFromGem
  module ExtendFromGem
    def say_hello
      super + ' World'
    end
  end

  refine FromGem do
    prepend ExtendFromGem
  end
end

FromGem.new.say_hello
# => 'Hello'
# We haven't activated our Refinement yet!

using ExtendedFromGem

FromGem.new.say_hello
# => 'Hello World'
# There it is!

现在,我们想要写的是:

class A 
  def test1
    using ExtendedFromGem
    FromGem.new.say_hello
  end

  def test2
    FromGem.new.say_hello
  end
end

A.new.test1
# => 'Hello World'

A.new.test2
# => 'Hello'

不幸的是,这不起作用:细化仅在脚本范围内有效,在这种情况下,细化仅在调用 using 之后 处于活动状态,或者它们在模块中工作范围,在这种情况下,它们对整个模块主体都是活动的,甚至在之前调用using,所以我们可以 做,这是(IMO,这更干净):

Unfortunately, that doesn't work: Refinements only work in script scope, in which case Refinements are only active after the call to using, or they work in module scope, in which case they are active for the whole module body, even before the call to using, so what we can do, is this (IMO, this is cleaner):

class A 
  using ExtendedFromGem

  def test1
    FromGem.new.say_hello
  end
end

class A 
  def test2
    FromGem.new.say_hello
  end
end

A.new.test1
# => 'Hello World'

A.new.test2
# => 'Hello'

或者这个:

class A 
  def test2
    FromGem.new.say_hello
  end
end

using ExtendedFromGem

class A 
  def test1
    FromGem.new.say_hello
  end
end

A.new.test1
# => 'Hello World'

A.new.test2
# => 'Hello'

等等:test1 看到了改进,test2 没有.

Et voilà: test1 sees the refinement, test2 doesn't.

这篇关于如何为特定方法启用猴子补丁?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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