Лучшая практика для обозначения устаревшего кода в Ruby?
Я хотел бы отметить метод как устаревший, поэтому люди, использующие его, могут легко проверить свой код и догнать. В Java вы устанавливаете @Deprecated, и все знают, что это значит.
Итак, есть ли предпочтительный способ (или даже инструменты) для отметки и проверки на упущения в Ruby?
Ответы
Ответ 1
Для почти всех случаев, в зависимости от библиотеки или метапрограммирования для устаревания, излишне. Просто добавьте комментарий к rdoc и вызовите метод Kernel#warn
. Например:
class Foo
# <b>DEPRECATED:</b> Please use <tt>useful</tt> instead.
def useless
warn "[DEPRECATION] `useless` is deprecated. Please use `useful` instead."
useful
end
def useful
# ...
end
end
Если вы используете Yard вместо rdoc, ваш комментарий к доктору должен выглядеть следующим образом:
# @deprecated Please use {#useful} instead
Наконец, если вы придерживаетесь tomdoc, сделайте свой комментарий следующим:
# Deprecated: Please use `useful` instead
Устаревший: указывает, что метод устарел и будет удален в будущей версии. Вы ДОЛЖНЫ использовать это для документирования методов, которые были общедоступными, но будут удалены в следующей крупной версии.
Кроме того, не забывайте удалить устаревший метод в будущем (и правильно semver 'd) release. Не делайте те же ошибки, что и библиотеки Java.
Ответ 2
Стандартная библиотека Ruby имеет модуль с логикой предупреждения: http://ruby-doc.org/stdlib-1.9.3/libdoc/rubygems/rdoc/Gem/Deprecate.html. Я предпочитаю его поддерживать мои сообщения об устаревании стандартным образом:
# my_file.rb
class MyFile
extend Gem::Deprecate
def no_more
close
end
deprecate :no_more, :close, 2015, 5
def close
# new logic here
end
end
MyFile.new.no_more
# => NOTE: MyFile#no_more is deprecated; use close instead. It will be removed on or after 2015-05-01.
# => MyFile#no_more called from my_file.rb:16.
Обратите внимание, что при таком подходе вы получите бесплатную информацию о том, где был проведен вызов.
Ответ 3
Если вы хотите быть средним (под угрозой быть полезным), вы можете распечатать первую строку стоп-кода во время предупреждения, чтобы разработчики знали, где они используют устаревший вызов.
Это означает, что Я уверен, что это поразительно.
warn Kernel.caller.first + " whatever deprecation message here"
При правильном использовании это будет включать абсолютный путь к файлу и строке, в которой использовался устаревший вызов. Дополнительная информация о Kernel:: caller доступна здесь
Ответ 4
Использование ActiveSupport:
class Player < ActiveRecord::Base
def to_s
ActiveSupport::Deprecation.warn('Use presenter instead')
partner_uid
end
end
Предупреждения отключены в рабочей среде по умолчанию.
Ответ 5
Вы также можете использовать ActiveSupport::Deprecation
(доступно в версии 4.0+):
require 'active_support/deprecation'
require 'active_support/core_ext/module/deprecation'
class MyGem
def self.deprecator
ActiveSupport::Deprecation.new('2.0', 'MyGem')
end
def old_method
end
def new_method
end
deprecate old_method: :new_method, deprecator: deprecator
end
MyGem.new.old_method
# => DEPRECATION WARNING: old_method is deprecated and will be removed from MyGem 2.0 (use new_method instead). (called from <main> at file.rb:18)
Ответ 6
У вас есть libdeprecated-ruby
(2010-2012, больше не доступно на rubygem в 2015 году)
Небольшая библиотека, предназначенная для поддержки разработчиков, работающих с устаревшим кодом.
Идея исходит из языка программирования "D
", где разработчики могут отмечать определенный код как устаревший, а затем разрешить/запретить возможность выполнять устаревший код.
require 'lib/deprecated.rb'
require 'test/unit'
# this class is used to test the deprecate functionality
class DummyClass
def monkey
return true
end
deprecate :monkey
end
# we want exceptions for testing here.
Deprecate.set_action(:throw)
class DeprecateTest < Test::Unit::TestCase
def test_set_action
assert_raise(DeprecatedError) { raise StandardError.new unless DummyClass.new.monkey }
Deprecate.set_action(proc { |msg| raise DeprecatedError.new("#{msg} is deprecated.") })
assert_raise(DeprecatedError) { raise StandardError.new unless DummyClass.new.monkey }
# set to warn and make sure our return values are getting through.
Deprecate.set_action(:warn)
assert_nothing_raised(DeprecatedError) { raise StandardError.new unless DummyClass.new.monkey }
end
end
Ответ 7
Вы можете использовать шаблон класса Macros и написать что-то вроде этого:
class Module
def deprecate(old_method, new_method)
define_method(old_method) do |*args, &block|
warn "Method #{old_method}() depricated. Use #{new_method}() instead"
send(new_method, *args, &block)
end
end
end
class Test
def my_new_method
p "My method"
end
deprecate :my_old_method, :my_method
end
Ответ 8
При использовании рельсов у вас есть метод отклонения модуля #.
Ответ 9
Canivete - это драгоценный камень, который позволяет вам упростить и элегантно осудить ваши методы. Немного об этом здесь.
Ответ 10
В итоге я собрал легкий метод:
def deprecate(msg)
method = caller_locations(1, 1).first.label
source = caller(2, 1).first
warn "#{method} is deprecated: #{msg}\ncalled at #{source}"
end
Затем, чтобы отклонить метод, вставьте вызов в тело метода (или конструктор для класса)
def foo
deprecate 'prefer bar, will be removed in version 3'
...
end
Он довольно декларативный и обеспечивает ведение журнала соответствующей информацией. Я не очень люблю Rubyist, поэтому может понадобиться настройка/YMMV.
Ответ 11
Мы можем использовать внутренние методы макросов.
Пример:
class Foo
def get_a; puts "I'm an A" end
def get_b; puts "I'm an B" end
def get_c; puts "I'm an C" end
def self.deprecate(old_method, new_method)
define_method(old_method) do |*args, &block|
puts "Warning: #{old_method} is deprecated! Use #{new_method} instead"
send(new_method, *args, &block)
конец конец
не рекомендуется: a,: get_a не рекомендуется: b,: get_b не рекомендуется: c,: get_c
конец
o = Foo.new
р о