恼人的“警告:已初始化常量”消息的解决方案


68

今天,我偶然发现了一个有关Ruby常量的棘手问题。在我们的团队中,有人创建了一个模块,该模块包含在多个模型中。在我们的(规格)测试输出中,此结果会生成警告消息,例如:

/home/ayrton/project/lib/life_cycle.rb:5:警告:已初始化常量RESET

解决此问题的一种方法是,像这样声明常量:

module LifeCycle

  unless (const_defined?(:RESET))
    RESET = 'reset'
  end

  #...
end

我还阅读了由Avdi Grimm撰写的博客文章,该文章提供了一种替代解决方案,我想知道您对此事有何看法。


您是说它require在多个模型中是d还是included?应该只有一次,即使装载required多次
马克-安德烈·Lafortune

Answers:


125

我今天也遇到了同样的问题,找到了一个简单的解决方案。

由于警告是试图重新分配具有相同值的常量,因此我只是更改了

module LifeCycle
  RESET = 'reset'
end

module LifeCycle
  RESET ||= 'reset'
end

这可以解决警告,并且比检查是否定义了每个常量要简单得多。如果您找到更好的解决方案,请告诉我。


2
这可以非常巧妙地处理警告。
Valerio Schiavoni 2015年

3
如果警告是由重新加载您的类引起的,则记忆是一个很好的解决方案。如果您要覆盖第三方类的常量,则将警告保留在适当的位置会更安全。
Thiago Figueiro

这适用于Ruby,但Rubocop抛出时做的错误:An error occurred while Style/MutableConstant cop was inspecting <file>
安东尼

1
我忘记了这一点,但是当您使用require_relative时,它是完美的解决方案
Nils_e

22

这只是在显式重新加载的应用程序(例如Rails应用程序)中存在的问题。

如果冗长得罪您,则可以将其unless用作语句修饰符:

module LifeCycle
  RESET = 'reset' unless const_defined?(:RESET)
end

这给Avdi的建议仅使用方法留下了一些薄弱的论点:

  • 常量查找比方法查找快,
  • 常量值是在加载时定义的,而不是在(第一个)请求中定义的,
  • 常数从视觉上暗示他们不需要做任何工作,并且

如果您足够喜欢Avdi的建议而忽略这些建议,请继续使用。


实际上,这实际上是一个Rails应用程序,我担心,这unless const_defined?是一个掩盖问题而不是实际解决问题的解决方案。

1
如果问题是源重新加载,则将其掩盖。否则,它解决了。:-)
sheldonh

6

如果RESET在您的代码中不断变化,则它不是一个常数。如果将其重命名为小写的“重置”,问题将消失。Ruby认为大写变量是常量,因此显示错误以警告您常量已更改。


我只是运行“刀客户端列表”。我不知道或修改任何变量
P Satish Patro
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.