ruby-on-rails - view教程 - 创建rails项目




Ruby混合和调用超级方法 (4)

好吧,所以我一直在我的小Rails应用程序中重构我的代码,以消除重复,一般来说让我的生活更轻松(因为我喜欢简单的生活)。 这个重构的一部分,一直是将我的两个模型中通用的代码移动到一个模块,我可以将其包含在我需要的地方。

到现在为止还挺好。 看起来它会运行,但我刚刚遇到一个问题,我不知道如何解决。 该模块(我称之为“可发送”)只是处理传真,电子邮件或打印文档PDF的代码。 所以,例如,我有一个采购订单,我有内部销售订单(想象力缩写为ISO)。

我碰到的问题是,我想在加载对象后初始化一些变量(对于拼写不正确的人初始化:P),所以我一直在使用after_initialize钩子。 没问题,直到我开始添加一些mixin。

我所after_initialize的问题是,我可以在任何一个after_initialize中都有一个after_initialize ,所以我需要在开始时包含一个超级调用,以确保其他mixin after_initialize调用被调用。 这真是太棒了,直到我打电话给超级电话,我得到一个错误,因为没有超级电话。

这里有一个小例子,如果我没有足够的困惑:

class Iso < ActiveRecord::Base
  include Shared::TracksSerialNumberExtension
  include Shared::OrderLines
  extend  Shared::Filtered
  include Sendable::Model

  validates_presence_of   :customer
  validates_associated    :lines

  owned_by                :customer
  order_lines             :despatched # Mixin

  tracks_serial_numbers   :items  # Mixin

  sendable :customer                      # Mixin

  attr_accessor :address

  def initialize( params = nil )
    super
    self.created_at ||= Time.now.to_date
  end
end

因此,如果每个mixin都有一个after_initialize调用,并且有一个超级调用,那么我怎样才能阻止最后一次超级调用? 在我打电话之前,如何测试超级方法的存在?


而不是检查超级方法是否存在,你可以定义它

class ActiveRecord::Base
    def after_initialize
    end
end

这在我的测试中起作用,不应该破坏你现有的任何代码,因为所有其他定义它的类都会默默地覆盖这个方法


你尝试过alias_method_chain吗? 你可以基本上链接所有的after_initialize调用。 它像一个装饰器:每个新的方法增加了一个新的功能层,并将控制权交给“重写”方法来完成剩下的工作。


你可以在这里抛出一个快速的条件:

super if respond_to?('super')

你应该没问题 - 不要添加无用的方法; 不错,干净。


你可以使用这个:

super if defined?(super)

这里是一个例子:

class A
end

class B < A
  def t
    super if defined?(super)
    puts "Hi from B"
  end
end

B.new.t




ruby