如何在Ruby中将一个类标记为已弃用?

9
在Ruby(尤其是Rails)中,将方法标记为已弃用非常容易。
但是我如何将整个类标记为已弃用?我想在使用类时发出警告:
class BillingMethod
end

BillingMethod.new #=> DEPRECATION WARNING: the class BillingMethod is deprecated. Use PaymentMethod instead.

或者当它用于继承时:

class Sofort < BillingMethod
end

Sofort.new #=> DEPRECATION WARNING: the class BillingMethod is deprecated. Use PaymentMethod instead. 

或者,在嵌套类中使用:

class BillingMethod::Sofort < BillingMethod
end

BillingMethod::Sofort.new #=> DEPRECATION WARNING: the class BillingMethod is deprecated. Use PaymentMethod instead. 

我认为class_eval块是放置这样的警告的地方。那是正确的位置吗?或者还有更好的方法吗?
3个回答

11

您可以查看Ruby标准库的一部分Deprecate

require 'rubygems'

class BillingMethod
  extend Gem::Deprecate

  class << self
    deprecate :new, "PaymentMethod.new", 2016, 4
  end

  # Will be removed April 2016, use `PaymentMethod.new` instead
  def initialize 
    #...
  end
end

使用已过时的方法将导致如下警告:

BillingMethod.new
# => NOTE: BillingMethod#new is deprecated; use PaymentMethod.new instead. It will be removed on or after 2016-04-01.
# => BillingMethod#new called from file_name.rb:32.

1
这只会在对象初始化时引发警告,而不是当类被用作父类或用于嵌套类树中时。或者我错过了重要的细节吗? - berkes
@berkes 您可以使用上述方法来弃用inherited钩子(类方法),从而弃用继承:class BillingMethod; class << self; deprecate :inherited, :none, 2016, 4; end; end。从BillingMethod继承现在应该会发出弃用警告。 - Petr Skocik
示例中的代码是错误的。因为:new是一个类方法,所以你需要将extend...deprecate行包装在class << self块中。 - berkes
@berkes,我修复了我的示例。 - spickermann

5

您可以使用const_missing来废除常量,从而间接使类过时。

当引用未定义的常量时,会调用const_missing

module MyModule

  class PaymentMethod
    # ...
  end

  def self.const_missing(const_name)
    super unless const_name == :BillingMethod
    warn "DEPRECATION WARNING: the class MyModule::BillingMethod is deprecated. Use MyModule::PaymentMethod instead."
    PaymentMethod
  end
end

这样做使得现有引用MyModule::BillingMethod的代码仍然能够工作,并且提醒用户他们使用了已弃用的类。这是我目前看到的最好的弃用类方法。

在你的例子中,当你刚刚定义了const_missing,它会如何被触发? - berkes
@berkes,第一部分不应该存在,这是打字错误。 - Andrey Deineko
const_missing 方法中,PaymentMethod\n end 到底是实现了什么功能? - berkes
1
当在模块中引用未定义的常量时,将调用const_missing函数。它会返回一个值(在这种情况下是PaymentMethod),以供该常量使用。 - Andrey Deineko
在我看来,在关闭 const_missing 方法之前的最后一个 end 是多余且不正确的。在 Ruby 2.1.x 中,它会导致语法错误。 - berkes

-2
为什么不这样做:
def initialize(*args)
  warn "DEPRECATION WARNING: ..."
  super
end

作者希望在所有类的使用(例如继承)中显示警告,而不仅仅是新对象的创建。 - hedgesky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接