Перебирать только общедоступные константы Ruby

Начиная с Ruby 2.0 или около того, можно было сделать константу приватной, используя private_constant, что приводит к ошибке, если константа используется непосредственно вне модуля объявления.

Однако constants и const_defined? по-прежнему возвращает частные константы, а const_get разрешает доступ к ним. Есть ли способ программно определить частные константы и отфильтровать их во время выполнения?

(Примечание: Что делает Module.private_constant? Есть ли способ перечислить только частные константы? и его ответ не специально адресовать этот случай, а скорее наоборот (как перечислить только константы private).)


Обновление: похоже, что в Ruby 1.9 и 2.0 constants включает только общедоступные константы. Начиная с 2.1, constants без аргументов по-прежнему включает только общедоступные константы, но установка inherit на false с constants(false) (т. е. список только констант, определенных в этом модуле, а не в его модулях-предках) имеет побочный эффект раскрытия частных констант.


person David Moles    schedule 03.05.2016    source источник
comment
Возможный дубликат stackoverflow.com/questions/12944616/   -  person Dave Schweisguth    schedule 03.05.2016
comment
Они еще определены. Ты хочешь, чтобы Руби солгала?   -  person tadman    schedule 03.05.2016
comment
Я не повторяю вашу проблему в Ruby 2.1.4: 2.1.4 :001 > module Foo; X = 1; Y = 2; private_constant :Y; end; Foo.constants возвращает [:X]   -  person Neil Slater    schedule 03.05.2016
comment
@tadman Нет, я просто отмечаю, что пробовал.   -  person David Moles    schedule 03.05.2016
comment
@NeilSlater Это интересно. Когда я пытаюсь свести его к минимальному тестовому случаю, я его тоже не вижу.   -  person David Moles    schedule 03.05.2016
comment
@DavidMoles: Если у вас есть код, который манипулирует константами, возможно, как часть фреймворка, он может удалить и снова добавить их. Я предполагаю, что это может удалить частный флаг, если код не знал, что это необходимо для их сохранения. Я прочитал источник для private_constant, и кажется, что флаг добавляется непосредственно к константе (это не отдельный поиск), поэтому, если вы удаляете константу, вы неявно удаляете ее статус частного флага.   -  person Neil Slater    schedule 03.05.2016
comment
@NeilSlater Похоже, это связано с флагом inherit - см. правки.   -  person David Moles    schedule 03.05.2016
comment
@DaveSchweisguth Этот вопрос связан, но на самом деле он противоположен тому, что я пытаюсь сделать, и его текущий ответ не совсем правильный.   -  person David Moles    schedule 03.05.2016


Ответы (1)


Вы можете идентифицировать константы следующим образом:

class A
  C = "value"
  private_constant :C
  C2 = "value2"
end

A.constants #public constants
#=> [:C2]
A.constants(false) #public & private constants
#=> [:C, :C2]
A.constants(false) - A.constants #private constants
#=> [:C]
person Ilya    schedule 03.05.2016
comment
OP, похоже, хочет массив незакрытых констант и говорит, что метод constants возвращает все константы (они хотят отфильтровать частные константы). Однако я согласен с тем, что это работает, а также A.constants возвращает [:C2], как и ожидалось, - и то, что, по-видимому, хочет ОП, - поэтому не совсем уверен, в чем реальная проблема ОП. - person Neil Slater; 03.05.2016
comment
@NeilSlater, я ответил на ответ Is there a way to programmatically identify private constants? - person Ilya; 03.05.2016
comment
Новое редактирование показывает все возможные способы. Не могу с этим поспорить :-) Интересно, почему в вопросе говорится, что это не работает для OP? - person Neil Slater; 03.05.2016
comment
@NeilSlater Я передавал (false) в коде, где я думал, что у меня проблема. Не было очевидно, что inherit= имеет какое-либо отношение к общедоступному/частному, поэтому я не видел, что это может быть проблемой. - person David Moles; 03.05.2016