Rails:environment.rbに必要なlibファイルで定義されたフィルターは、実稼働環境のfilter_chainから消えます。どうして?

StackOverflow https://stackoverflow.com/questions/620146

質問

私の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.rbconfig.cache_classestrueから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が呼び出されます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top