为什么不能用Ruby声明方法中的常量?

Fin*_*las 2 ruby constants

考虑以下情况,StubFoo是Foo的存根,我希望将其用于某些测试.

class Runner

  def run
      Foo = StubFoo
      foo = Foo.new
      # using Foo...
  end

end
Run Code Online (Sandbox Code Playgroud)

这会生成以下错误消息: Dynamic constant assignment

然而,在RSpec我可以做以下工作,这是有效的,并且完全合法:

it "should be an example" do
  Foo = StubFoo
  foo = Foo.new
  foo.to_s.should == "I am stubbed!"
end
Run Code Online (Sandbox Code Playgroud)

关于这一点的一些问题.

  • 为什么这适用于RSpec测试用例,而不是上述方法?
  • 据我所知,"它"只是RSpec中的一种方法,但我能够在"方法"中重新声明一个常量.

我在使用模拟框架之前做这个,纯粹想知道如何在Ruby中进行模拟,存根等等.我听说动态语言更容易模拟/存根,并且互联网上有指南,其中简单的类重新分配如上所述.根据我的研究,在Ruby中,不可能在方法中声明常量,但我如上所述会感到困惑.

编辑

对,这开始变得更有意义了.我已经更新了run,现在正在使用const_set.

  def run
      old = Foo
      self.class.const_set(:Foo, StubFoo)
      foo = Foo.new
      puts foo.to_s
      self.class.const_set(:Foo, old)
      foo = Foo.new
      puts foo.to_s
  end
Run Code Online (Sandbox Code Playgroud)

这会产生一个警告,然而,这是什么/如何模拟框架在Ruby中工作?显然更优雅,功能齐全,但他们只是压制这个警告?

sep*_*p2k 9

您无法使用方法定义重新分配常量Constant = value.但是,您可以使用它重新分配它们const_set.基本上它意味着阻止,但不是禁止,动态不断重新分配.

至于为什么它适用it:是的,it是一种方法,但你没有定义,你在称它.重新分配发生在您作为参数传递的块内it.

Blocks继承创建它们的上下文的类型.这意味着在块内部,self.class.name将是您的测试类的名称.因此,当您在传递给it方法的块内定义常量时,实际上是在测试类上定义常量.