如何最好地以向后兼容的方式重命名Ruby模块?我有ActiveSupport,因此可以通过这种方式调用弃用警告,但是在这种情况下,我弃用了旧的模块名称,而不是方法名称。
示例如下:
module OldName
def self.method1
...
end
end
将成为:
module NewName
def self.method1
...
end
end
我想生成警告,指示开发人员使用NewName::method1
而不是OldName::method1
有什么建议吗?
答案 0 :(得分:2)
ActiveSupport提供了两种弃用常量的方法:DeprecatedConstantAccessor和DeprecatedConstantProxy。它们在显示警告的时间(访问器是在访问它的时候;代理是在其方法被调用时)以及它们通常如何行为方面的取舍和限制。您可能想要同时尝试这两种方法,看看哪种方法适合您的用例。
答案 1 :(得分:2)
Rails 4.1.8 Ruby 2.2.0p0
module Fred
extend self
def aaa; end
def bbb; end
def ccc; end
def ddd; end
def eee; end
end
module Bar
extend self
def ccc; end
end
ActiveSupport::Deprecation.deprecate_methods(Fred, :aaa, bbb: :zzz, ccc: 'use Bar#ccc instead')
Fred.aaa
DEPRECATION WARNING: aaa is deprecated and will be removed from Rails 4.2. (called from __pry__ at (pry):15)
=> nil
在Rails 5.2.0中尝试了相同的代码,但没有 DEPRECATION WARNING 。
Rails 5.2.0 Ruby 2.5.1p57
class Fred
def aaa; end
def bbb; end
def ccc; end
def ddd; end
def eee; end
end
class Bar
def ccc; end
end
ActiveSupport::Deprecation.deprecate_methods(Fred, :aaa, bbb: :zzz, ccc: 'use Bar#ccc instead')
> Fred.new.aaa
DEPRECATION WARNING: aaa is deprecated and will be removed from Rails 6.0 (called from irb_binding at (irb):13)
=> nil
答案 2 :(得分:1)
您可以使用类似的内容:
module Bar
def self.aaa
'Bar::aaa'
end
def baz
'Bar#baz'
end
end
module Foo
{included: :include,extended: :extend,prepended: :prepend}.each do |mod_method, called_method|
singleton_class.define_method(mod_method) do |base|
warn "Foo is deprecated please use Bar instead"
base.send(called_method,Bar)
end
end
def self.method_missing(meth,*args,&block)
warn "Foo is deprecated please use Bar instead"
Bar.respond_to?(meth) ? Bar.send(meth,*args,&block) : super
end
end
class A
include Foo # this will throw a warning
end
然后
Foo.aaa
# Foo is deprecated please use Bar instead
#=> 'Bar::aaa'
A.new.baz
#=> 'Bar#baz'
答案 3 :(得分:0)
module OldName
def instance_method(*args)
yield(args)
end
instance_methods.each do |im|
alias_name = "_#{im.to_s}"
alias_method alias_name, im
define_method(im) do |*args, &block|
warn "Foo is deprecated please use Bar instead"
public_send(alias_name, *args, &block)
end
end
end
class C
include OldName
end
C.instance_methods && [:im, :_im]
#=> [:im, :_im]
c = C.new
c._instance_method(2,3) { |a,b| a+b }
#=> 5
c.instance_method(2,3) { |a,b| a+b }
# Foo is deprecated please use Bar instead
#=> 5
或者,public_send(alias_name, *args, &block)
可以替换为method(alias_name).call(*args, &block)
。
答案 4 :(得分:0)
我被修补的宝石中的一个错误所困扰,这导致了一些错误的开始,但是最终答案非常简单,我将工作代码作为其他示例的例子:
require 'active_support'
OldName = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('OldName', 'NewName')
module NewName
def self.method1
puts 'Hello World!'
end
end
NewName.method1
#=> Hello World!
OldName.method1
#=> DEPRECATION WARNING: OldName is deprecated! Use NewName instead. (called from ..)
#=> Hello World!
简单!
感谢@matthewd向我指出了正确的方向。