我正在使用的一个gem(gem"A")依赖于另一个我正在尝试修补其方法的gem(gem"B")。当我修补gem"B"并从gem"a"调用一个方法时,monkey补丁将被忽略。我的补丁如下所示:
module B
class<< self
def patched_method()
raise
end
end
end
我在整个过程中插入了语句来打印方法的位置,使用格式
puts B.method(:patched_method).source_location
当在补丁之前调用时,它指向宝石"B"的位置。补丁之后,它指向我定义补丁的位置,但它仍然不调用我的补丁!
现在,我的补丁只调用raise
,这样我就可以验证它是否被调用了,但我也尝试过打印文本和调用实际的补丁代码,但都不起作用。我做错了什么?
宝石和代码细节
我正在尝试修补Numerizer
-gem的numerize
方法,该方法由Chronic
-gem使用。
我尝试过多种方法进行修补,但最近的是:
module NumerizerExpand
module ClassMethods
def self.numerize(value)
raise
end
end
def self.included(receiver)
receiver.extend ClassMethods
end
end
Numerizer.send(:include, NumerizerExpand)
和
Numerizer.instance_eval do
class<< self
def my_numerize(value)
puts "here"
raise
end
alias_method :numerize, :my_numerize
end
end
对于第二种方法,我尝试过同时使用instance_eval
和module_eval
,但似乎都不起作用。
我在github上创建了一个要点,其中包含我正在运行的测试脚本。
您正在修补错误的类:)
require 'numerizer'
require 'chronic'
puts Chronic::Numerizer.method(:numerize).source_location
class Chronic::Numerizer
def self.numerize(value)
puts "here"
raise
end
end
puts Chronic::Numerizer.method(:numerize).source_location
#p Chronic::Numerizer.numerize(3)
p Chronic.parse('January 2nd')
输出
bbozo@eva:~/dev/SO_question_1$ ruby wii.rb
/home/bbozo/.rvm/gems/ruby-2.2.3/gems/chronic-0.10.2/lib/chronic/numerizer.rb
72
wii.rb
8
here
wii.rb:10:in `numerize': unhandled exception
from /home/bbozo/.rvm/gems/ruby-2.2.3/gems/chronic-0.10.2/lib/chronic/parser.rb:100:in `pre_normalize'
from /home/bbozo/.rvm/gems/ruby-2.2.3/gems/chronic-0.10.2/lib/chronic/parser.rb:226:in `tokenize'
from /home/bbozo/.rvm/gems/ruby-2.2.3/gems/chronic-0.10.2/lib/chronic/parser.rb:60:in `parse'
from /home/bbozo/.rvm/gems/ruby-2.2.3/gems/chronic-0.10.2/lib/chronic.rb:90:in `parse'
from wii.rb:17:in `<main>'
显然,chronic
团队决定不想将一个类作为单独的依赖项来维护,他们只是将其复制粘贴并包含在名称空间中。
你在修补一块实际上chronic
没有使用的宝石。猪的把戏:)但对chronic
人来说是合理的。
Numerizer
是一个类,numerize
是一个方法。您不能使用模块覆盖类方法,因为ruby按以下顺序查找方法:
- 类
- 包含/扩展模块
- 父类
- 父类模块
- 对象
- 对象包含的模块
- 基本对象
这应该很简单,不确定你是否尝试过?
class Numerizer
def self.numerize(string)
# override it here
end
end
我希望这能奏效,除非你先这样做,然后require 'numerizer'
在这种情况下,您将覆盖您的更改。
PS。很抱歉我还没有测试过这个,但我不想安装一个需要我运行sudo gem sources -a http://gemcutter.org
的gem我不知道如何扭转这种操作,也不会在谷歌上搜索。
PPS。如果这不起作用,我会非常惊讶。