Как пометить класс как устаревший в Ruby?

В 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 было бы место, куда воткнуть такое предупреждение. Это правильное место? Или есть лучшие методы?


person berkes    schedule 17.04.2015    source источник


Ответы (3)


Вы можете использовать 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, продолжать работать и предупреждает пользователя об использовании устаревшего класса.

Это лучшее, что я видел до сих пор, для устаревшего класса.

person Andrey Deineko    schedule 17.04.2015
comment
В вашем примере, как будет запущен const_missing, если вы определили его чуть выше? - person berkes; 17.04.2015
comment
@berkes первой части там быть не должно, опечатка - person Andrey Deineko; 17.04.2015
comment
В методе const_missing чего именно достигает PaymentMethod\n end? - person berkes; 17.04.2015
comment
const_missing вызывается, когда делается ссылка на неопределенную константу в модуле. Он возвращает значение (в данном случае PaymentMethod), которое будет использоваться для этой константы. - person Andrey Deineko; 17.04.2015
comment
Мне кажется, что последний end непосредственно перед закрытием метода const_missing избыточен и некорректен. В Ruby 2.1.x выдает синтаксическую ошибку. - person berkes; 17.04.2015

Вы можете взглянуть на Deprecate< /a>, которая является частью стандартной библиотеки Ruby:

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

Использование метода deprecated приведет к такому предупреждению:

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.
person spickermann    schedule 17.04.2015
comment
Это вызовет предупреждения только при инициализации объекта. Не тогда, когда класс используется как родитель или используется во вложенном дереве классов. Или я упускаю важную деталь? - person berkes; 17.04.2015
comment
@berkes Вы можете использовать приведенное выше, чтобы отказаться от хука inherited (метод класса), тем самым отказавшись от наследования: class BillingMethod; class << self; deprecate :inherited, :none, 2016, 4; end; end. Наследование от BillingMethod теперь должно выдавать предупреждение об устаревании. - person PSkocik; 17.04.2015
comment
Код в примере неверный. Поскольку :new — это метод класса, вам нужно заключить extend...deprecate строк в блок class << self. - person berkes; 17.04.2015
comment
@berkes, я исправил свой пример. - person spickermann; 17.04.2015

Почему бы не сделать это так:

def initialize(*args)
  warn "DEPRECATION WARNING: ..."
  super
end
person Gena Shumilkin    schedule 17.04.2015
comment
Автор хочет показывать предупреждение обо всех случаях использования классов (например, о наследовании), а не только о создании новых объектов. - person hedgesky; 17.04.2015