0

私の Rails アプリケーションでは、lib にファイルがあり、とりわけ、すべてのコントローラーで実行されるフィルターを設定します。

開発環境で実行すると、すべて正常に動作します。ただし、生産中はフィルターがなくなります。面白いことに、 を調べると、filter_chain他のフィルターが残っていることに気付きました。プラグインで定義されたもの、または後で特定のコントローラー クラスで定義されたもの。

Rails Edge と v2.3.0 の両方でこれをテストしました。

テストの更新:

古いレールでテストしたところ、v2.1.0 に戻って問題が発生していることがわかりましたが、v2.0.5 では発生していませ


この動作を次の小さなテスト ケースに分離しました。

# 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、テスト アプリケーションは正常に動作します。

クラスのリロードがなぜそのようなことを引き起こしているのか、私はまだ疑問に思っています。

4

2 に答える 2

3

RailsリストのFrederickCheungが答えを出しました:

cache_classesはそれ以上のことをするからです。フィルタが機能する前の方法では、Foo <Barの場合、その時点でBarで定義されたフィルタのみがFooに継承されます。後日、それらをBarに追加しても何も起こりません。

開発モードでは、アプリが起動し、ファイルが必要になり、ActionController::Baseにフィルターが追加されます。その後、最初の要求が発生し、コントローラーがロードされ、そのフィルターを継承します。

cache_classesがtrueの場合、すべてのアプリケーションクラスが事前にロードされます。これはファイルが必要になる前に発生するため、そのファイルの実行時にすべてのコントローラーがすでに存在しているため、効果はありません。初期化子からこのファイルを要求することでこれを解決できます(アプリクラスがロードされる前に実行されるようにします)が、実際には、これをapplication.rbに配置するだけではどうでしょうか。

フレッド


私の実際のケースは実際にはもっと複雑で、これが問題を解決するために私が見つけた方法です。

config.after_initialize do
  require 'foobar'
end

このafter_initializeブロックは、フレームワークが初期化された後、アプリケーションファイルをロードする前に実行されるため、ActionPack::Baseロードされた後、アプリケーションコントローラーがロードされる前に影響を受けます。

これが、本番環境で行われるすべてのプリロードを処理するための一般的に安全な方法だと思います。

于 2009-03-06T21:58:22.533 に答える
0

ルビースクリプトをドロップします

RAILS_ROOT \ config \ initializers

が含まれています

require "foobar.rb"

これにより、before_filterが呼び出されます。

于 2009-03-06T21:58:45.013 に答える