在Ruby 2.3.4中打破了类级别常量

时间:2017-05-18 06:40:06

标签: ruby ruby-2.3

我有一些代码可以简化为以下内容。它适用于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设为私有。在@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]

Ruby 2.3.3和2.3.4

#<Dummy:0x007fbd6d162380>

1 个答案:

答案 0 :(得分:2)

如何修复

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是开源的。在bug #12478中修复了that commit。提交的消息明确指出它在处理非模块对象时会改变行为。

符号分别为not convertedString并单独处理,:TEST未在Dummy级别和could not be resolved in different context上展开。

为什么它不是错误

在单例类上声明常量没有任何意义(请查看旧代码):

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

在遗留实现中成功解决了常量,与乘以两个负数得到肯定结果完全相同:错误被否定。代码无法正常工作,它偶尔会以意想不到的方式失败两次,但会产生正确的结果。