ピュア ルビーの場合:
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 の新しいバージョンは、どのファイルが実際に変更されたかを判断するのにも非常に優れており、それらのファイルのみをリロードします。したがって、次のコントローラーがあるとします。
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 サーバーを停止してから開始する必要があります。しかし、開発中に定数を変更する可能性は、実際のコードと比較すると少し低く、それほど頻繁ではありません。既に述べたように、これは製品コードにはまったく影響しません。
編集:active_reload gemへのリンクを追加