[#109207] [Ruby master Feature#18915] New error class: NotImplementedYetError or scope change for NotImplementedYet — Quintasan <noreply@...>
Issue #18915 has been reported by Quintasan (Michał Zając).
18 messages
2022/07/14
[ruby-core:109369] [Ruby master Feature#18948] Add `with_private_method` option to `private_constant`
From:
"jeremyevans0 (Jeremy Evans)" <noreply@...>
Date:
2022-07-29 14:49:37 UTC
List:
ruby-core #109369
Issue #18948 has been updated by jeremyevans0 (Jeremy Evans).
okuramasafumi (Masafumi OKURA) wrote in #note-2:
> In a real world code I'm facing, `M1` contains lots of other methods so including it in `InstanceMethods` causes confusion.
You should be able to work around this by making sure the M1 namespace surrounds the method in question, so unqualified constant lookup works:
```ruby
module M1
CONST = 'CONST'.freeze
private_constant :CONST
end
module M2
def self.included(base)
base.include M1
base.include InstanceMethods
end
module ::M1
module ::M2::InstanceMethods
def const?(value)
CONST == value
end
end
end
end
class C
include M2
end
C.new.const?('CONST') # => true
```
I don't think this need is common enough to support in `private_constant`. If you really need a private method defined that returns the constant value, you can always define it manually.
----------------------------------------
Feature #18948: Add `with_private_method` option to `private_constant`
https://bugs.ruby-lang.org/issues/18948#change-98512
* Author: okuramasafumi (Masafumi OKURA)
* Status: Open
* Priority: Normal
----------------------------------------
## Problem
I have the following code:
```ruby
module M1
CONST = 'CONST'.freeze
end
module M2
def self.included(base)
base.include M1
base.include InstanceMethods
end
module InstanceMethods
def const?(value)
M1::CONST == value
end
end
end
class C
include M2
end
C.new.const?('CONST') # => true
```
`M2` module "inherits" `M1` module using `included` hook. This code works, but I prefer making constants private. However, when I add `private_constant :CONST` to `M1` then the code doesn't work anymore since we cannot refer `M1::CONST`.
## Workaround
One way to solve this is to define method that just returns the private constant.
```ruby
# Refined version of M1 with `const` method
module M1
CONST = 'CONST'.freeze
private_constant :CONST
private
def const
CONST
end
end
# Refined version of M2, using `const` method inherited from M1
module M2
def self.included(base)
base.include M1
base.include InstanceMethods
end
module InstanceMethods
def const?(value)
const == value
end
end
end
```
This works anyway, but defining private method for every private constant could be cumbersome.
## Solution
So my suggestion here is to add `with_private_method` option to `private_constant` method. The auto-generated private method has the same name as the given constant and just returns it. So we can do the following:
```ruby
module M1
CONST = 'CONST'.freeze
private_constant :CONST, with_private_method: true
end
```
Now we can access `CONST` with `const` method. This makes is possible to refer private constants through private methods more easily, that helps some code like my example.
--
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>