我正在使用 active_admin,我在 Rails 3 应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:
class Foo
BAR = "bar"
end
然后,我在每个必须在我的 Rails 应用程序中重新加载一些代码的请求中收到此警告:
/Users/pupeno/helloworld/app/admin/billing.rb:12: warning: already initialized constant BAR
知道发生了什么以及如何避免这些警告吗?
最佳答案
在纯 Ruby 中:
class A
TEST = "foo"
end
puts A::TEST
# foo
class A
TEST = "bar"
end
# (irb): warning: already initialized constant TEST
puts A::TEST
# bar
在 Ruby 中,您可以随时打开一个类并重新声明其中的任何内容。它仅针对常量发出警告,但它确实继续进行更改。
让我们重写代码更简洁一点:
class A
TEST = "foo"
TEST = "bar"
end
# (irb):3: warning: already initialized constant TEST
即使您没有真正更改常量,只是将其设置为相同的值,也会出现警告。
class A
TEST = "foo"
TEST = "foo"
end
# (irb):3: warning: already initialized constant TEST
总的来说,它只是一个可以安全忽略的警告。
在 Rails 中:
在开发过程中,Rails 会重新加载您的应用程序中任何更改的代码。较新版本的 Rails 也非常聪明地找出哪些文件实际发生了更改,然后仅重新加载这些文件。所以假设你有这个 Controller :
class TestController < ApplicationController
FOO = "bar"
def index
...
end
end
如果您在其中进行任何更改,该文件将重新加载。重新加载文件时,再次解析 FOO = "bar"
,您最终会收到相同的警告。
解决方案:
如果您使用的是 Rails 3.0 或 3.1,请尝试 active_reload gem 并查看您的警告是否消失(它可能在重新加载它们之前卸载您的类,这可能导致警告消失)
使用以下定义常量:
FOO = "bar" unless const_defined?(:FOO)
只有当常量不存在时,这才会定义常量。所以你会避免警告。
使用辅助方法定义常量并自动执行此操作
module ConstDefiner def define_constant(name, value) const_set(name, value) unless const_defined?(name) end end ActionController::Base.send :extend, ConstDefiner ActiveRecord::Base.send :extend, ConstDefiner # Now in all your controllers/models: # instead of FOO = "value" unless const_defined?(:FOO), use: define_constant :FOO, "value"
这些警告仅在开发模式下发生。您将不需要所有的
unless const_defined?(:FOO)
在生产中。通常不建议在生产中使用特定于开发的代码(除非它真的非常必要)请记住,当您说
FOO = "bar"unless const_defined?(:FOO)
时,即使您真的更改了FOO
常量,一旦定义,它就不会重新加载。您必须停止并启动 rails server 才能重新加载它。但是在开发过程中修改常量的概率与实际代码相比有点低,不是很频繁。如前所述,这不会以任何方式影响生产代码。
编辑:添加了指向 active_reload gem 的链接
关于ruby-on-rails - active_admin 目录中的常量警告重新声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17028102/