为什么不能在Ruby的方法中声明常量? [英] Why can you not declare constants in methods with Ruby?

查看:111
本文介绍了为什么不能在Ruby的方法中声明常量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下内容,StubFoo是Foo的存根,我希望对它进行一些测试。

Consider the following, StubFoo is a stub of Foo, which I wish to stub out for some tests.

class Runner

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

end

这将生成以下错误消息:动态常量分配

This generates the following error message: Dynamic constant assignment

但是,在RSpec中,我可以执行以下操作,并且完全合法:

Yet, in RSpec I can do the following, which works and is perfectly legal:

it "should be an example" do
  Foo = StubFoo
  foo = Foo.new
  foo.to_s.should == "I am stubbed!"
end

对此有一些疑问。


  • 为什么这可以用于RSpec测试用例,但不适用于上面的方法?

  • 据我所知,它只是RSpec中的一种方法,但是我可以在方法中重新声明一个常量。

我正在这样做在使用模拟框架之前,纯粹是想了解Ruby中的模拟,存根等等的区别。我听说动态语言更易于模拟/存根,并且Internet上有一些指南,其中如上所述进行了简单的类重新分配。根据我的研究,在Ruby中无法在方法中声明常量,但是如上所述,我很困惑。

I'm doing this prior to using a mocking framework for purely wanting to know how mocking, stubbing etc... is different in Ruby. I hear that dynamic languages are easier to mock/stub, and there are guides on the Internet in which simple class reassignment is done as above. From my research, in Ruby it's not possible to declare constants within a method, yet I'm confused as mentioned above.

编辑

对,这开始变得更有意义了。我已将run更新为现在使用const_set。

Right, this is starting to make more sense. I've updated run to be using const_set now.

  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

这会产生警告,但这是那么在Ruby中什么/模拟框架如何工作?显然要优雅得多,并且功能齐全,但是他们只是抑制了这个警告吗?

This generates a warning however, is this what/how mocking frameworks work then in Ruby? Obviously much more elegant and feature full, but do they simply repress this warning?

推荐答案

您不能使用 Constant = value 。但是,您可以使用 const_set 重新分配它们。基本上,这是要阻止但不禁止动态常量重新分配。

You can't reassign constants in method definitions using Constant = value. You can however reassign them using const_set. Basically it's meant to discourage, but not disallow, dynamic constant reassignment.

关于为什么与 it 一起使用的原因:是的, it 是一种方法,但是您没有定义它,而是在调用它。重新分配发生在作为参数传递给 it 的块内。

As to why it works with it: Yes, it is a method, but you're not defining, you're calling it. The reassignment takes place inside the block which you pass as an argument to it.

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

Blocks inherit the type of the context in which they are created. This means that inside the block, self.class.name would be the name of your test class. Therefore, when you define a constant inside the block passed to the it method, you're actually defining a constant on your test class.

这篇关于为什么不能在Ruby的方法中声明常量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆