139

我想将一个方法标记为已弃用,以便使用它的人可以轻松检查他们的代码并赶上进度。在 Java 中,您设置了 @Deprecated 并且每个人都知道这意味着什么。

那么有没有首选的方法(甚至工具)来标记和检查 Ruby 中的弃用情况?

4

11 回答 11

170

对于几乎所有情况,依赖库或元编程来弃用是过大的。只需向 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 版本)中删除不推荐使用的方法。不要犯与 Java 库一样的错误。

于 2008-11-16T17:09:44.690 回答
66

Ruby 标准库有一个带有警告逻辑的模块:https ://ruby-doc.org/stdlib/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.

请注意,通过这种方法,您将免费获得有关通话地点的信息。

于 2014-05-09T00:11:58.233 回答
18

使用 ActiveSupport:

class Player < ActiveRecord::Base
  def to_s
    ActiveSupport::Deprecation.warn('Use presenter instead')
    partner_uid
  end
end

生产环境默认关闭警告

于 2016-08-03T09:32:56.117 回答
14

如果您想变得刻薄(以乐于助人为幌子),您可以在警告期间打印出调用堆栈的第一行,让开发人员知道他们在哪里使用了已弃用的调用。

这很刻薄,因为我很确定它会影响性能。

warn Kernel.caller.first + " whatever deprecation message here"

正确使用时,这将包括文件的绝对路径和使用过时调用的行。有关 Kernel::caller 的更多信息可在此处获得

于 2010-05-25T22:29:47.017 回答
13

您还可以使用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)
于 2013-06-27T09:42:28.163 回答
8

你确实有libdeprecated-ruby(2010-2012,2015 年不再在 ruby​​gem 上可用)

一个小型库,旨在帮助开发人员使用已弃用的代码。
这个想法来自 ' 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
于 2008-11-16T15:31:12.487 回答
3

您可以使用类宏模式并编写如下内容:

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
于 2012-02-07T06:47:43.960 回答
3

使用 rails 时,您有 Module#deprecate 方法。

于 2012-02-07T11:34:39.913 回答
2

Canivete是一个宝石,它使您能够以简单而优雅的方式弃用您的方法。更多关于它的信息

于 2010-08-01T11:50:05.030 回答
1

最后我总结了一个轻量级的方法:

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。

于 2016-06-15T00:46:23.397 回答
0

我们可以使用内部宏方法。例子:

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 poa

于 2019-09-04T13:26:56.987 回答