Вызов Super из метода с псевдонимами - PullRequest
1 голос
/ 04 июня 2009

Я пытаюсь немного высушить мой код, поэтому я пишу метод, чтобы отложить или делегировать определенные методы другому объекту, но только если он существует. Вот основная идея: у меня есть Shipment < AbstractShipment, который может иметь Reroute < AbstractShipment. Либо Shipment, либо Reroute может иметь Delivery (или поставки), но не оба.

Когда я вызываю shipment.deliveries, я хочу, чтобы он проверил, нет ли у него перенаправления в первую очередь. Если нет, просто вызовите метод AbstractShipment deliveries; если так, делегируйте метод к перенаправлению.

Я попробовал это с простым кодом ниже:

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'

Я немного искал и нашел эту ссылку , в которой говорится, что это ошибка в Ruby 1.8, но исправлена ​​в 1.9. К сожалению, я пока не могу обновить этот код до 1.9, так что у кого-нибудь есть предложения по обходным путям?

Спасибо: -)

Редактировать: После небольшого просмотра моего кода я понял, что на самом деле мне не нужно псевдоним всех методов, которые я сделал, на самом деле мне нужно было только перезаписать метод доставки, так как остальные три фактически называют это своими расчетами. Тем не менее, я все равно хотел бы узнать ваши мысли, поскольку я сталкивался с этим раньше.

1 Ответ

2 голосов
/ 05 июня 2009

Вместо того, чтобы использовать 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

Использование прямой оценки обеспечивает хорошие характеристики производительности и позволяет вам иметь простой декларативный синтаксис для того, что вы делаете в определении класса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...