1

我使用 shared_examples_for 在 rspec 中包含了来自模块的常量

shared_examples_for 'Constants' do
  include AllTestData.UserConstants
end
# for example I have AllTestData.UserConstants::USER_NAME = 'John Dorian'

describe Users do
  include_context 'Constants'
  p USER_NAME   
end

当我使用 ruby​​ 1.9.2 时,它可以工作。现在我使用 ruby​​ 2.0.0。现在是引发错误 - NameError: uninitialized constant USER_NAME

为什么现在它失败了,我该如何解决?谢谢

4

1 回答 1

3

这与常量查找规则的变化有关。有关一些历史,请参阅John Firebaugh 的 Making Sense of Constant Lookup in Ruby。您会注意到,在 1.8 中,当一个对象的实例被instance_eval不断查找时,它是按词法执行的。这在 1.9 中发生了变化。事实上,1.9 有几次迭代,并且class_eval不断查找版本之间并不一致。

似乎在 Ruby 2.0 中,不断查找的规则又回到了 1.8 的方式。所以现在,instance_execRSpec 非常依赖,回到词法常数规则,不会向上搜索层次结构。

您可以看到这一点:

class Foo
  X = "Does it work?"
end

f = Foo.new
f.instance_exec do
  p X
end

在 Ruby 1.9.2 中,这会输出:“它有用吗?”

在 Ruby 2.0.0 中,这会输出:NameError: uninitialized constant X

您可以通过以下方式委派给班级来解决此问题self.class::CONSTANT

module Bar
  B = "A bit wonky"
end

example_group = Class.new do
  include Bar
end

example = example_group.new

example.instance_exec do
  p self.class::B
end
# => "A bit wonky"
于 2013-11-13T21:38:47.873 回答