6

私はactive_adminを使用しており、モデルとページの宣言を持つRails 3アプリのアプリにディレクトリ管理者がいます。時々私もクラスを持っていて、そのクラスが次のように定数を持っている場合:

class Foo
  BAR = "bar"
end

その後、Rails アプリでコードを再ロードする必要があるすべてのリクエストで、次の警告が表示されます。

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

何が起こっているのか、これらの警告を回避する方法はありますか?

4

1 に答える 1

10

ピュア ルビーの場合:

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へのリンクを追加

于 2013-06-22T08:59:23.940 に答える