Skip to content

jeremyevans/ruby-deprecate_public

Repository files navigation

ruby-deprecate_public

ruby-deprecate_public exists so that library authors can take an existing public method in one of their classes, and make it a private method, but still allow it to be called as a public method, emitting a warning if called as a public method.

On Ruby 2.6+, you can also take an existing public constant, make it a private constant, but still allow it to be accessed as a public constant, emitting a warning if accessed as a public constant.

Usage

Basic

require 'deprecate_public'
class Foo
  private

  def meth
    :return_value
  end
end

foo = Foo.new

foo.send(:meth)
# => :return_value

foo.meth
# raises NoMethodError: private method `meth' called for ...

Foo.deprecate_public :meth
foo.meth
# warning emitting: "calling Foo#meth using deprecated public interface"
# => :return_value

## Ruby 2.6+: Deprecating Constants

class Foo
  BAR = 1
  private_constant :BAR
end

Foo::BAR
# raises NameError: private constant Foo::BAR referenced

Foo.deprecate_public_constant :Bar
Foo::BAR
# warning emitting: "accessing Foo::BAR using deprecated public interface"
# => 1

Arguments

# Deprecate multiple methods at once
deprecate_public([:meth1, :meth2])

# Override message
deprecate_public(:meth1, "meth1 is private method, stop calling it!")

# Ruby 2.6+: deprecate_public_constant uses same interface

Design

deprecate_public works by overriding method_missing, which is called if you call a private method with a specified receiver. That’s one of the reasons calling a private method raises NoMethodError instead of MethodVisibilityError or something like that.

On Ruby 2.6+, deprecate_public_constant works by overriding const_missing, which is called if you access a constant using the public interface (Foo::BAR in the above example).

Caveats

Before Ruby 3, while you can call deprecate_public on a Module, you should only do so if the module has not been included in another Module or Class, as when called on a module it only affects future cases where the module was included in a class.

While you can call deprecate_public_constant on a Module, you should only do so if the module has not been included in another Module or Class, as when called on a module it only affects future cases where the module was included in a class, even in Ruby 3.

Installation

ruby-deprecate_public is distributed as a gem, and can be installed with:

gem install deprecate_public

Source

ruby-deprecate_public is hosted on GitHub:

https://github.com/jeremyevans/ruby-deprecate_public

Issues

ruby-deprecate_public uses GitHub Issues for issue tracking:

https://github.com/jeremyevans/ruby-deprecate_public/issues

Author

Jeremy Evans <code@jeremyevans.net>

About

Warn when calling private methods via public interface

Resources

Stars

Watchers

Forks

Languages