Kitebuggy
Kitebuggy

Reputation: 99

Deprecating an old module name in Ruby?

How would I best go about renaming a Ruby Module in a backwards compatible manner? I have ActiveSupport, so can call deprecation warnings this way, but in this case I'm deprecating the old module name and not the method names.

Example follows:

module OldName
  def self.method1
    ...
  end
end

Will become:

module NewName
  def self.method1
    ...
  end
end

I want to generate warnings directing the developer to using NewName::method1 rather than OldName::method1

Any suggestions?

Upvotes: 0

Views: 578

Answers (5)

Kitebuggy
Kitebuggy

Reputation: 99

I was sideswiped by a bug in the gem I was patching, which caused a few false starts, but the final answer is extremely simple and I include the working code as an example for others:

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!

Simples!

My thanks to @matthewd for re-pointing me in the right direction.

Upvotes: 0

praaveen V R
praaveen V R

Reputation: 1261

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

Same code tried in rails 5.2.0 but no 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 

Upvotes: 2

Cary Swoveland
Cary Swoveland

Reputation: 110695

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

Alternatively, public_send(alias_name, *args, &block) can be replaced with method(alias_name).call(*args, &block).

Upvotes: 0

engineersmnky
engineersmnky

Reputation: 29478

You could go with something like:

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

Then

Foo.aaa
# Foo is deprecated please use Bar instead
#=> 'Bar::aaa'

A.new.baz  
#=> 'Bar#baz'

Upvotes: 1

matthewd
matthewd

Reputation: 4435

ActiveSupport provides two ways of deprecating a constant: DeprecatedConstantAccessor and DeprecatedConstantProxy. They each have trade-offs and limitations in when they show the warning (Accessor is when it's accessed; Proxy is when its methods are called) and how they generally behave. You'll probably want to try both to see which one feels right for your use case.

Upvotes: 2

Related Questions