Je voudrais marquer une méthode comme obsolète, afin que les personnes qui l'utilisent puissent facilement vérifier leur code et rattraper leur retard. Dans Java vous définissez @Deprecated et tout le monde sait ce que cela signifie.
Existe-t-il donc un moyen préféré (ou même des outils) pour marquer et vérifier les dépréciations dans Ruby?
Dans presque tous les cas, dépendre d'une bibliothèque ou d'une méta-programmation pour une dépréciation est exagéré. Ajoutez simplement un commentaire au rdoc et appelez le Kernel#warn
méthode. Par exemple:
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
Si vous utilisez Yard au lieu de rdoc , votre commentaire de doc devrait ressembler à ceci:
# @deprecated Please use {#useful} instead
Enfin, si vous adhérez à tomdoc , faites ressembler votre commentaire à ceci:
# Deprecated: Please use `useful` instead
Obsolète: indique que la méthode est obsolète et sera supprimée dans une future version. Vous DEVRIEZ utiliser ceci pour documenter des méthodes qui étaient publiques mais qui seront supprimées à la prochaine version majeure.
De plus, n'oubliez pas de supprimer la méthode obsolète dans une version future (et correctement semver 'd) . Ne faites pas les mêmes erreurs que les bibliothèques Java ont fait.
Ruby Standard Library possède un module avec la logique d'avertissement: http://Ruby-doc.org/stdlib-1.9.3/libdoc/rubygems/rdoc/Gem/Deprecate.html . J'ai tendance à préférer maintenir mes messages de dépréciation de manière "standard":
# 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.
Notez qu'avec cette approche, vous obtiendrez gratuitement des informations sur le lieu de l'appel.
Si vous voulez être méchant (sous prétexte d'être utile), vous pouvez imprimer la première ligne de la pile d'appels pendant un avertissement pour faire savoir aux développeurs où ils utilisent un appel déconseillé.
C'est méchant parce que je suis presque sûr que c'est une performance-hit.
warn Kernel.caller.first + " whatever deprecation message here"
Lorsqu'il est utilisé correctement, cela inclura le chemin absolu vers le fichier et la ligne où l'appel obsolète a été utilisé. Plus d'informations sur Kernel :: caller sont disponibles ici
Utilisation d'ActiveSupport:
class Player < ActiveRecord::Base
def to_s
ActiveSupport::Deprecation.warn('Use presenter instead')
partner_uid
end
end
Les avertissements sont désactivés dans l'environnement de production par défaut
Vous pouvez aussi utiliser ActiveSupport::Deprecation
(disponible dans la version 4.0+), en tant que tel:
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)
Vous avez libdeprecated-Ruby
(2010-2012, plus disponible sur rubygem en 2015)
Une petite bibliothèque destinée à aider les développeurs à travailler avec du code obsolète.
L'idée vient du langage de programmation 'D
', où les développeurs peuvent marquer certains codes comme obsolètes, puis autoriser/interdire la possibilité d'exécuter du code obsolète.
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
Vous pouvez utiliser le modèle de macros de classe et écrire quelque chose comme ceci:
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
Lorsque vous utilisez Rails, vous disposez de la méthode Module # obsolète.
J'ai fini par jeter ensemble une méthode légère:
def deprecate(msg)
method = caller_locations(1, 1).first.label
source = caller(2, 1).first
warn "#{method} is deprecated: #{msg}\ncalled at #{source}"
end
Ensuite, pour déprécier une méthode, insérez un appel dans le corps de la méthode (ou un constructeur pour une classe)
def foo
deprecate 'prefer bar, will be removed in version 3'
...
end
Il est assez déclaratif et fournit une journalisation avec des informations pertinentes. Je ne suis pas vraiment un Rubyist, donc il faudra peut-être peaufiner/YMMV.