【问题标题】:Monkey patch class methods猴子补丁类方​​法
【发布时间】:2012-08-19 03:53:43
【问题描述】:

我正在尝试在 ActiveShipping UPS class 中进行一些猴子修补。

我需要添加一个类级别的方法(以.self 开头),所以这就是我想要做的:

module ActiveMerchant
  module Shipping
    class UPS < Carrier
      def self.process_request(receiver, sender, packages, options = {})
        # some code
      end

      def regular_method
        "foobar"
      end
    end
  end
end

不幸的是,当我尝试使用它时:

 ActiveMerchant::Shipping::UPS.process_request(receiver etc) 

我收到一个错误:

NoMethodError: undefined method `process_request' for ActiveMerchant::Shipping::UPS:Class
        from (irb):6
        from C:/Ruby19/bin/irb.bat:19:in `<main>'

原始类中没有名为process_request 的类方法。

在 gem 中提供的原始 UPS 类中,定义了一种静态方法 self.retry_safe = true 我可以毫无错误地使用它。

我也可以在创建 UPS 类的实例后使用regular_method

提供更多详细信息:
我正在使用 Rails 2.3 ( :-( ) 和 Ruby 1.9.2。我对环境没有影响。

猴子补丁代码在plugins/my_plugin/lib/active_shipping/ext/carriers/ups.rb

在 /active_shipping 中,我有一个名为 extensions.rb 的文件,其中有:

require 'active_shipping'

require_relative 'ext/carriers'
require_relative 'ext/carriers/ups'

它处理正确加载所有内容(我想基于我问题中第一块代码的regular_method 行为)。

我尝试在我的一个控制器中调用 process_request。这部分有点棘手,因为我正在使用这样的东西:

MyModel.courier_service.process_request(parameters)

其中courier_service,在这种情况下包含ActiveMerchant::Shipping::UPS 类。

我还是 Ruby 的新手,不知道我应该提供什么样的细节。

【问题讨论】:

    标签: ruby class monkeypatching


    【解决方案1】:

    也许你想用另一种方式来做

    文件patch_classes.rb:

    module ActiveMerchant展开 模块运输 模块类方法 def self.process_request(receiver, sender, packages, options = {}) # 一些代码 结尾 结尾 模块实例方法 def 常规方法 “美食吧” 结尾 结尾 def self.included(接收者) receiver.extend 类方法 receiver.send :include, InstanceMethods 结尾 结尾 结尾

    然后你必须加载你的类“ActiveMerchant::Shipping::UPS” 然后你可以通过

    将你的方法附加到你的类 Rails.configuration.to_prepare 做 require_dependency [[ActiveMerchant::Shipping::UPS 的文件]] 需要'patch_classes') ActiveMerchant::Shipping::UPS.send(:include, ::ActiveMerchantExpand::Shipping) 结尾

    这是来自 Rails 插件的编写,希望对您有所帮助。

    问候 tingel2k

    【讨论】:

    • 我终于使用简单的猴子补丁实现了我的目标,但这可能是更好的方法。当我有时间重构那段代码时,我会想到它。谢谢
    【解决方案2】:

    您是否明确地将 require 文件与您的猴子补丁一起使用?如果你只是将它放在你的应用程序或 lib 路径下而不需要,它不会加载,因为常量 ActiveMerchant::Shipping::UPS 是在 gem 中定义的,它不会触发依赖解析机制。

    【讨论】:

    • 据我了解,我认为 blid 正确地需要该文件。否则他将无法像他所说的那样调用regular_method。
    • 是的,我的文件已加载,正如李静解释的那样。
    • @blid,您能否提供更多详细信息。因为对我来说它看起来很奇怪,没有错字,一切看起来都很好。据我所知,没有办法防止猴子修补。顺便说一句,您也可以尝试 ActiveMerchant::Shipping::UPS.singleton_methods 打印出 UPS 的所有类方法,当然在您的情况下它不会包含 process_request。
    • @Jing Li:我按照您的要求提供了详细信息,如果我可以添加更多内容,请告诉我。
    • 感谢您的详细信息!不幸的是,我仍然看不到出了什么问题。您显示来自 irb(rails 控制台?)的 NoMethodError 异常,您可以添加来自控制器的完整回溯吗?它应该在log/development.log。您是否在控制台和控制器中测试了regular_method?另外,您能否展示一下MyModel.courier_service 是如何设置的,以及您插件的init.rb: plugins/my_plugin/init.rb 的内容?
    猜你喜欢
    • 1970-01-01
    • 2011-04-15
    • 2023-04-08
    • 2012-07-26
    • 1970-01-01
    • 2016-09-01
    • 2012-09-16
    • 2012-12-18
    • 2020-01-09
    相关资源
    最近更新 更多