如何为特定方法启用猴子补丁? [英] How to enable monkey patch for specific method?
问题描述
我正在使用 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屋!