猴子补丁类方​​法

时间:2012-08-23 15:16:15

标签: ruby class monkeypatching

我正在尝试在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。我对环境没有影响。

Monkey修补代码位于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 beheaviour来自第一块代码)。

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

MyModel.courier_service.process_request(parameters)

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

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

2 个答案:

答案 0 :(得分:2)

也许你想以另一种方式做到这一点

文件patch_classes.rb:

module ActiveMerchantExpand
  module Shipping
    module ClassMethods
      def self.process_request(receiver, sender, packages, options = {})
        # some code
      end
    end

    module InstanceMethods
      def regular_method
        "foobar"
      end
    end

    def self.included(receiver)
      receiver.extend         ClassMethods
      receiver.send :include, InstanceMethods
    end
  end
end

然后你必须加载你的班级“ActiveMerchant :: Shipping :: UPS” 之后,您可以通过

将您的方法附加到课程中
Rails.configuration.to_prepare do
  require_dependency [[file for ActiveMerchant::Shipping::UPS]]
  require 'patch_classes' )
  ActiveMerchant::Shipping::UPS.send(:include, ::ActiveMerchantExpand::Shipping)
end

这是来自rails插件的写作,我希望这有帮助。

关于tingel2k

答案 1 :(得分:1)

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