https://redmine.ruby-lang.org/https://redmine.ruby-lang.org/favicon.ico?17113305112018-01-22T13:12:21ZRuby Issue Tracking SystemRuby master - Feature #14382: Make public access of a private constant call const_missinghttps://redmine.ruby-lang.org/issues/14382?journal_id=696772018-01-22T13:12:21ZEregon (Benoit Daloze)
<ul></ul><p>Isn't Module#deprecate_constant specifically for this usage?</p> Ruby master - Feature #14382: Make public access of a private constant call const_missinghttps://redmine.ruby-lang.org/issues/14382?journal_id=696782018-01-22T14:41:51Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul></ul><p>Eregon (Benoit Daloze) wrote:</p>
<blockquote>
<p>Isn't Module#deprecate_constant specifically for this usage?</p>
</blockquote>
<p><code>Module#deprecate_constant</code> deprecates all usage of the constant, both public and private. If you want to keep a constant but change the visibility from public to private, it isn't appropriate.</p> Ruby master - Feature #14382: Make public access of a private constant call const_missinghttps://redmine.ruby-lang.org/issues/14382?journal_id=697322018-01-24T05:35:48Zmatz (Yukihiro Matsumoto)matz@ruby.or.jp
<ul></ul><p>The idea seems OK to me. Can you experiment?</p>
<p>Matz.</p> Ruby master - Feature #14382: Make public access of a private constant call const_missinghttps://redmine.ruby-lang.org/issues/14382?journal_id=697352018-01-24T06:17:45Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul></ul><p>matz (Yukihiro Matsumoto) wrote:</p>
<blockquote>
<p>The idea seems OK to me. Can you experiment?</p>
</blockquote>
<p>With the attached patch, both test-all and test-spec pass.</p>
<p>The only time I can see this causing an issue is in a class/module that overrides <code>const_missing</code> to do something, but also has private constants, and wants an exception raised instead of <code>const_missing</code> being called for public access to a private constant. That seems very unlikely to me. Usually if <code>const_missing</code> is used, it is designed to handle all constants to do something. For example, let's say you overrode <code>const_missing</code> to call a singleton method of the same name, so you could call singleton methods that start with a capital letter using <code>klass::Method</code> syntax without parentheses:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Foo</span>
<span class="no">Bar</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">private_constant</span> <span class="ss">:Bar</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">const_missing</span><span class="p">(</span><span class="n">const</span><span class="p">)</span>
<span class="nb">send</span><span class="p">(</span><span class="n">const</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>In this case, assume <code>Foo::Bar</code> constant is an implementation detail. It is probably desired that external use of <code>Foo::Bar</code> call <code>Foo.Bar()</code>, but currently this is not possible as an exception is raised before calling <code>Foo.const_missing</code>.</p>
<p>Unless <code>const_missing</code> is overridden, this will not change any behavior. I don't usually use <code>const_missing</code> in any of my applications/libraries, but assuming this is accepted I plan to use this in the deprecate_public gem (<a href="https://github.com/jeremyevans/ruby-deprecate_public" class="external">https://github.com/jeremyevans/ruby-deprecate_public</a>) to add a <code>Module#deprecate_public_constant</code> 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.</p>
<p>If you have specific ideas for experimentation, I will definitely try them.</p> Ruby master - Feature #14382: Make public access of a private constant call const_missinghttps://redmine.ruby-lang.org/issues/14382?journal_id=701332018-02-02T14:36:57Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<ul></ul><p>In the case it is accessed from an inherited class, the receiver class/module may differ from class/module which defines the constant as private.<br>
So I think that the hook method will need another parameter.<br>
And as a private constant is not accessible but not "missing", different name may be better.</p> Ruby master - Feature #14382: Make public access of a private constant call const_missinghttps://redmine.ruby-lang.org/issues/14382?journal_id=701342018-02-02T15:09:30Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul></ul><p>nobu (Nobuyoshi Nakada) wrote:</p>
<blockquote>
<p>In the case it is accessed from an inherited class, the receiver class/module may differ from class/module which defines the constant as private.<br>
So I think that the hook method will need another parameter.</p>
</blockquote>
<p>Can you please let me know which hook method needs another parameter? Also, can you provide example code showing the problem, as I'm not sure I understand?</p>
<blockquote>
<p>And as a private constant is not accessible but not "missing", different name may be better.</p>
</blockquote>
<p>Are you referring to calling a method other than <code>const_missing</code>? Then it breaks the similarity with <code>method_missing</code>. Do you think we should also change ruby so that <code>obj.foo</code> where <code>foo</code> is a private method should call a method other than <code>method_missing</code>?</p> Ruby master - Feature #14382: Make public access of a private constant call const_missinghttps://redmine.ruby-lang.org/issues/14382?journal_id=724252018-06-06T18:29:33Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul><li><strong>File</strong> <a href="/attachments/7190">0001-Make-public-access-of-a-private-constant-call-const_.patch</a> <a class="icon-only icon-download" title="Download" href="/attachments/download/7190/0001-Make-public-access-of-a-private-constant-call-const_.patch">0001-Make-public-access-of-a-private-constant-call-const_.patch</a> added</li></ul><p>nobu (Nobuyoshi Nakada) wrote:</p>
<blockquote>
<p>In the case it is accessed from an inherited class, the receiver class/module may differ from class/module which defines the constant as private.<br>
So I think that the hook method will need another parameter.</p>
</blockquote>
<p>Attached is an updated patch against current trunk with an additional test showing use with nested constants, where the superclass calls <code>private_constant</code> and the subclass accesses the constant publicly. It shows that <code>const_missing</code> is still called on the subclass in that case, which I think is the most consistent behavior as that mirrors how <code>method_missing</code> works.</p>
<p>If this isn't the behavior you would expect in this case, can you please explain what behavior you expect?</p> Ruby master - Feature #14382: Make public access of a private constant call const_missinghttps://redmine.ruby-lang.org/issues/14382?journal_id=729632018-07-16T05:17:48Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Closed</i></li></ul>