Issue #14382 has been updated by jeremyevans0 (Jeremy Evans).


matz (Yukihiro Matsumoto) wrote:
> The idea seems OK to me. Can you experiment?

With the attached patch, both test-all and test-spec pass.

The only time I can see this causing an issue is in a class/module that overrides `const_missing` to do something, but also has private constants, and wants an exception raised instead of `const_missing` being called for public access to a private constant.  That seems very unlikely to me.  Usually if `const_missing` is used, it is designed to handle all constants to do something.  For example, let's say you overrode `const_missing` to call a singleton method of the same name, so you could call singleton methods that start with a capital letter using `klass::Method` syntax without parentheses:

~~~ ruby
class Foo
  Bar = 1
  private_constant :Bar

  def self.const_missing(const)
    send(const)
  end
end
~~~

In this case, assume `Foo::Bar` constant is an implementation detail.  It is probably desired that external use of `Foo::Bar` call `Foo.Bar()`, but currently this is not possible as an exception is raised before calling `Foo.const_missing`.

Unless `const_missing` is overridden, this will not change any behavior.  I don't usually use `const_missing` in any of my applications/libraries, but assuming this is accepted I plan to use this in the deprecate_public gem (https://github.com/jeremyevans/ruby-deprecate_public) to add a `Module#deprecate_public_constant` method, which will issue a deprecation warning if a constant is accessed through the public interface (no deprecation warning if accessed through the private interface).  This will allow libraries with public constants that are implementation details to deprecate public use of the constants in a way that alerts users of the libraries.

If you have specific ideas for experimentation, I will definitely try them.

----------------------------------------
Feature #14382: Make public access of a private constant call const_missing
https://bugs.ruby-lang.org/issues/14382#change-69735

* Author: jeremyevans0 (Jeremy Evans)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
Calling `obj.foo` where `foo` is a private method of `obj` calls `method_missing`. You would expect `klass::FOO` where `FOO` is a private constant of `klass` to call `const_missing`, but currently it doesn't.  This makes a small change so that `const_missing` will be called in such cases.
    
In addition to similarity to `method_missing`, the main reason for doing this is it offers a way to deprecate public constants.  Currently, if you have a public constant and want to make it a private constant, you can't do it without breaking possible callers.  With this patch, you can make it a private constant, then override `const_missing` in the class, and have `const_missing` print a deprecation warning and then return the value of the constant.

---Files--------------------------------
0001-Make-public-access-of-a-private-constant-call-const_.patch (2.68 KB)


-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>