Rails:environment.rbに必要なlibファイルで定義されたフィルターは、実稼働環境のfilter_chainから消えます。どうして?
-
03-07-2019 - |
質問
私のRailsアプリケーションには、libにあるファイルがあります。これは、とりわけ、すべてのコントローラーで実行されるフィルターをセットアップします。
開発環境で実行すると、すべてが正常に実行されます。ただし、実稼働環境では、フィルターは失われます。面白いことに、filter_chain
を調べると、他のフィルターが残っていることに気付きました。プラグインで定義されたもの、または後で特定のコントローラークラスで定義されたもの。
レールエッジとv2.3.0の両方でこれをテストしました。
テストの更新:
古いレールでテストした結果、問題がv2.1.0に戻っていることがわかりましたが、v2.0.5ではなく、それらを二分して 986aec5 rails commit to gilt。
次の小さなテストケースに動作を分離しました:
# app/controllers/foo_controller.rb
class FooController < ApplicationController
def index
render :text => 'not filtered'
end
end
# lib/foobar.rb
ActionController::Base.class_eval do
before_filter :foobar
def foobar
render :text => 'hi from foobar filter'
end
end
# config/environment.rb (at end of file)
require 'foobar'
開発環境で実行したときに得られる出力は次のとおりです。
$ script/server &
$ curl localhost:3000/foo
> hi from foobar filter
そして、本番環境環境の出力は次のとおりです。
$ script/server -e production &
$ curl localhost:3000/foo
> not filtered
前にも触れたように、プラグインを介して同じことを行うと、どの環境でも問題なく動作します。必要なのは、プラグインのlib/foobar.rb
ファイルのinit.rb
の下にあるものを置くことです。
だから、ある意味では回避策がありますが、何が起こっているのか、実稼働中にフィルターが失われる原因を理解したいのです
Railsがさまざまな環境でロードを処理するさまざまな方法の何かだと推測しますが、さらに深く掘り下げる必要があります。
更新
実際、次の設定行に絞り込みました。
config.cache_classes = false
production.rb
でconfig.cache_classes
がtrue
からfalse
に変更された場合、テストアプリケーションは正常に動作します。
なぜクラスのリロードがそのようなことを引き起こしているのだろうか。
解決
cache_classesはそれだけではありません。道 Foo <!> ltの場合、フィルターが機能する前。次に、バーで定義されたフィルターのみ その時点のバーはFooに継承されます-それらをバーに追加します 後日は何もしません
開発モードでは、アプリが起動し、ファイルが必要です、フィルター ActionController :: Baseに追加されました。その後、最初のリクエストが届き、 コントローラがロードされ、そのフィルタを継承します。
cache_classesがtrueの場合、すべてのアプリケーションクラスは 事前にロードされました。これは、ファイルが必要になる前に発生するため、 そのファイルが実行されると、すべてのコントローラーが既に存在するため、 効果がありません。これを解決するには、このファイルを イニシャライザ(アプリクラスがロードされる前に実行されるようにする)、しかし 本当になぜそうしないのですか?これをapplication.rbに入れるだけですか?
フレッド
実際のケースは実際にはもっと複雑で、これが問題を解決するために見つけた方法です:
config.after_initialize do
require 'foobar'
end
after_initialize
ブロックは、フレームワークが初期化された後、アプリケーションファイルをロードする前に実行されるため、ロード後、アプリケーションコントローラーがロードされる前にActionPack::Base
に影響します。
本番環境で行われるすべてのプリロードを処理する一般的に安全な方法だと思います。
他のヒント
Rubyスクリプトをドロップ
RAILS_ROOT \ config \ initializers
を含む
require "foobar.rb"
これにより、before_filterが呼び出されます。