Константа уровня класса сломана в Ruby 2.3.4

У меня есть код, который можно упростить до следующего. Работает на Ruby 2.3.3 и работает на 2.3.4. Это немного странно, и я приветствую предложения о том, как его переписать, а также объяснения, почему он ломается.

require 'forwardable'

class Dummy
  class << self
    TEST = {
      a: Dummy.new,
      b: Dummy.new
    }

    extend Forwardable

    def_delegators :TEST, :[]

    private :new
  end
end

puts Dummy[:a]

Ruby 2.3.3

#<Dummy:0x007fbd6d162380>

Ruby 2.3.4

NameError: uninitialized constant TEST

Цель состояла в том, чтобы только инициализировать TEST один раз и .new быть частным Memoizing @test переменная внутри [] метод не работает, потому что new является частным в момент создания хэша.

РЕДАКТИРОВАТЬ

Удаление Forwardable из уравнения исправляет проблемы, но мне все еще интересно, почему и мысли о том, как его улучшить.

class Dummy
  class << self
    TEST = {
      a: Dummy.new,
      b: Dummy.new
    }

    def [](key)
      TEST[key]
    end

    private :new
  end
end

puts Dummy[:a]

Руби 2.3.3 и 2.3.4

#<Dummy:0x007fbd6d162380>

1 ответ

Решение

Как исправить

require 'forwardable'

class Dummy
  Test = {
    a: Dummy.new,
    b: Dummy.new
  }

  class << self
    extend Forwardable

    def_delegators :"::Dummy::Test", :[]

    private :new
  end
end

puts Dummy[:a]

Зачем

Ruby с открытым исходным кодом. В этом коммите была исправлена ​​ошибка #12478. В сообщении коммита явно указывается, что оно меняет поведение при работе с немодульными объектами.

Символы не преобразуются в Stringи больше продаются отдельно, :TEST не расширяется Dummy уровень и константа не могут быть разрешены в другом контексте.

Почему это не ошибка

Нет смысла объявлять константы в одноэлементных классах (сверьтесь со старым кодом):

Dummy.constants
#⇒ []
Dummy.singleton_class.constants
#⇒ [:TEST]

Константа была успешно разрешена в устаревшей реализации точно так же, как умножение двух отрицательных значений дает положительный результат: ошибки сводятся на нет. Код не работал должным образом, иногда он дважды не удавался неожиданным, но ценным способом, давая правильный результат.

Другие вопросы по тегам