从别名方法调用超级

时间:2009-06-04 19:13:52

标签: ruby-on-rails ruby

我试图稍微干掉我的代码所以我正在编写一种方法来将某些方法推迟或委托给另一个对象,但前提是它存在。以下是基本想法:我Shipment < AbstractShipment可能有Reroute < AbstractShipmentShipmentReroute可以Delivery(或交付),但不能同时使用AbstractShipment

当我致电shipping.deliveries时,我希望它先检查是否有重新路由。如果没有,那么只需调用deliveries的{​​{1}}方法;如果是这样,请将方法委托给重新路由。

我用下面的简单代码尝试了这个:

module Kernel
  private
    def this_method
      caller[0] =~ /`([^']*)'/ and $1
    end        
end

class Shipment < AbstractShipment
  ...

  def deferToReroute
    if self.reroute.present?
      self.reroute.send(this_method)
    else
      super
    end
  end

  alias_method :isComplete?, :deferToReroute
  alias_method :quantityReceived, :deferToReroute
  alias_method :receiptDate, :deferToReroute
end

Kernel.this_method只是方便查找调用的方法。但是,调用super会抛出

super: no superclass method `deferToReroute'

我搜索了一下,发现this link讨论了这是Ruby 1.8中的一个错误,但在1.9中修复了。不幸的是,我还不能将此代码升级到1.9,那么有没有人有任何解决方法的建议?

谢谢: - )

编辑:在看了一下我的代码后,我意识到我实际上并不需要为我所做的所有方法添加别名,实际上我只需要覆盖交付方法其他三个实际上称它为计算。但是,自从我之前遇到过这个问题后,我仍然想知道你们的想法。

1 个答案:

答案 0 :(得分:2)

不是在这里使用alias_method,而是通过硬覆盖这些方法来提供更好的服务,例如:

class Shipment < AbstractShipment
  def isComplete?
    return super unless reroute
    reroute.isComplete? 
  end
end

如果你发现你每班5-10次这样做,你可以这样做更好:

class Shipment < AbstractShipment
   def self.deferred_to_reroute(*method_names)
     method_names.each do |method_name|
       eval "def #{method_name}; return super unless reroute; reroute.#{method_name}; end"
     end
   end
   deferred_to_reroute :isComplete?, :quantityReceived, :receiptDate
end

使用直接评估提供good performance characteristics,并允许您为类定义中的内容提供简单的声明性语法。