红宝石猴子修补模块的课堂方法

时间:2017-01-10 03:52:59

标签: ruby module monkeypatching

我使用的宝石(宝石" A")依赖于另一种宝石(宝石" B"),其方法是我尝试修补。当我修补宝石" B"并从gem" A"调用一个方法,忽略猴子补丁。我的补丁如下所示:

module B
  class<< self
    def patched_method()
      raise
    end
  end
end

我使用表格

在整个过程中插入语句以打印方法的位置
puts B.method(:patched_method).source_location

在补丁之前调用时,它指向gem&#34; B&#34;的位置。在补丁之后,它指向我已经定义补丁的位置,但它仍然没有调用我的补丁!

现在我的补丁只是调用了raise,因此我可以验证它是否已被调用,但我也尝试过打印文本并调用我的实际补丁代码,但这些代码都不起作用。我做错了什么?

宝石和代码细节

我试图修补Numerizer gem's numerize method使用的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_evalmodule_eval,但似乎都不起作用。

I've created a gist on github包含我正在运行以测试此内容的脚本。

2 个答案:

答案 0 :(得分:1)

a是一个类,Numerizer是一个方法。 您不能使用module来覆盖类方法,因为ruby按以下顺序查找方法:

  • 包含/扩展模块
  • 父类
  • 父级的课程模块
  • ...
  • 对象
  • 包含Object的模块
  • BasicObject

这应该很简单,不确定你是否尝试过它?

numerize

我希望这可行,除非您先执行此操作,然后class Numerizer def self.numerize(string) # override it here end end 在这种情况下,您将覆盖您的更改。

PS。 对不起,我没有对此进行过测试,但是我不能为安装一个需要我运行require 'numerizer'的宝石而烦恼 我不知道如何扭转这种操作,也不会谷歌。

PPS。 如果这不起作用,我会感到非常惊讶。

答案 1 :(得分:1)

你正在修补错误的课程:)

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使用的宝石。猪的伎俩:)但Alamofire.request("url") .responseJSON { response in if let arr = response.result.value as? [String:AnyObject] { let inrc = (arr["date"])! self.myfuncDate(str: inrc as! String) } } func myfuncDate(str: String) { let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd" let date = dateFormatter.date(from: str) currrentDate = date //currentDate is globalVariable } 人要合理。