active_admin目录中的常量警告重新声明

时间:2013-06-10 16:00:31

标签: ruby-on-rails ruby activeadmin

我正在使用active_admin,我在Rails 3应用程序中的应用程序中有一个目录管理员,其中包含模型和页面的声明。偶尔我也有一个类,当这个类有一个常数时,像这样:

class Foo
  BAR = "bar"
end

然后,我在每个必须在我的Rails应用程序中重新加载某些代码的请求中收到此警告:

/Users/pupeno/helloworld/app/admin/billing.rb:12: warning: already initialized constant BAR

有什么想法以及如何避免这些警告?

1 个答案:

答案 0 :(得分:8)

在纯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在确定哪些文件实际已更改时非常聪明,然后仅重新加载这些文件。所以假设你有这个控制器:

class TestController < ApplicationController
  FOO = "bar"

  def index
    ...
  end
end

如果您在此内部进行任何更改,则会重新加载此文件。重新加载文件后,将再次解析FOO = "bar",并最终收到相同的警告。

解决方案:

  • 如果您正在使用Rails 3.0或3.1,请尝试使用active_reload gem并查看您的警告是否消失(可能会卸载您的类,然后重新加载它们,< em>可能导致警告消失)

  • 使用以下命令定义常量:

    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服务器才能重新加载它。但是,与实际代码相比,在开发期间修改常量的概率有点低,而不是非常频繁。如前所述,这不会以任何方式影响生产代码。

编辑:添加了对active_reload gem的链接