web-dev-qa-db-ja.com

非推奨コードをRubyでマークするベストプラクティスは?

メソッドを非推奨としてマークしたいので、それを使用する人々は簡単にコードをチェックして追いつくことができます。 Javaで@Deprecatedを設定すると、誰もがこれが何を意味するかを知っています。

それでは、Rubyで非推奨をマークしてチェックするための好ましい方法(またはツール)がありますか?

121
blindgaenger

ほとんどすべての場合、ライブラリまたは非推奨のメタプログラミングに依存するのはやり過ぎです。 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

rdoc の代わりに Yard を使用している場合、docコメントは次のようになります。

# @deprecated Please use {#useful} instead

最後に、 tomdoc に従う場合は、コメントを次のようにします。

# Deprecated: Please use `useful` instead

非推奨:メソッドが非推奨であり、将来のバージョンで削除されることを示します。これを使用して、パブリックであったメソッドを文書化する必要がありますが、次のメジャーバージョンで削除されます。


また、非推奨のメソッドを将来的に削除することを忘れないでください(適切に semver 'd)release。 Javaライブラリが行ったのと同じ間違いをしないでください。

155
Ryan McGeary

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.

このアプローチを使用すると、通話が行われた場所に関する情報が無料で得られることに注意してください。

46

あなたが意地悪になりたい場合(有用であるという軽underの下)、警告中にコールスタックの最初の行を印刷して、廃止されたコールを使用している場所を開発者に知らせることができます。

これは、パフォーマンスのヒットだと確信しているためです

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

正しく使用すると、非推奨の呼び出しが使用されたファイルと行への絶対パスが含まれます。 Kernel :: callerに関する詳細情報が利用可能です here

13
Adam French

ActiveSupportの使用:

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

本番環境ではデフォルトで警告がオフになっています

12
Artur Beljajev

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)
10
Kris

libdeprecated-Ruby (2010-2012、2015年のrubygemではもう利用できません)

廃止されたコードで作業する開発者を支援するための小さなライブラリ。
アイデアは、開発者が特定のコードを非推奨としてマークし、非推奨コードの実行を許可/禁止できるプログラミング言語「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
VonC

クラスマクロパターンを使用して、次のように記述できます。

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
3
Alex Djioev

Railsを使用する場合、Module#deprecateメソッドがあります。

3

Canivete は、シンプルでエレガントな方法でメソッドを非推奨にすることができるgemです。それについてもう少し こちら

1
skalee

私は軽量のメソッドを一緒に投げることになりました:

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が必要になるかもしれません。

1
Matt Whipple