2009-08-14 6 views
0

私は、Ruby on Rails 2.3.2でフィルターチェーンを使ってより動的に作業する方法を知りたいと思います。Ruby on Rails FilterChain内部 - 再ロード可能にする方法は?

現在、フィルタチェーンはクラスがロードされるときに構築されます。私は、クラスがロードされた後のある時点でフィルタチェーンが再構築されることを特に必要としています。

これは、フィルタチェーンはMyController用に構築された後、このようなことを行うことができます拡張子を使用していますRailsのプロジェクト(スプリー、ラディアントはまた、私は推測している影響を受ける可能性がある)を行うことです。

MyController.class_eval do 
    before_filter :my_filter_method 
end 

ApplicationController.class_eval do 
    before_filter :app_filter_method 
end 

ここでの問題は、app_filter_methodフィルタではなく、をMyControllerフィルタチェーンに追加することです。これは、MyControllerのフィルタチェーンが、ApplicationControllerのフィルタチェーンの以前のコピーから構築されているためです。このApplicationControllerのフィルタチェーンのコピーはではなく、ではまだapp_filter_methodフィルタが適用されています。

私は今のところれるFilterChainの再建がで起こりうることを2ヶ所と考えることができます:それはMyController.filter_chain

2で呼び出されるたびに)オンデマンドでリロード)

1。 MyController.reload_filter_chainは、チェーン内のMyControllerのサブクラスのフィルタを使用して、フィルタチェーンを再構築します。

おそらく、それぞれの要求に対してフィルタチェーンを構築するReloadableFilterChainのようなFilterChainのサブクラスを指定すると、それは可能でしょうか?私はいくつかの洞察力を持っているかもしれないここにあなたのいくつかを期待していた

The filter_chain method (line 573)

The FilterChain class (line 10)

はここでRailsの2.3.2にRuby用のGitHubの、上filters.rbのソースへのリンクですまたはこれを行う方法に関する助言。

ご迷惑をおかけして申し訳ございません。

エリオット

要求されるようにもっと詳しく:

シュプレー川が動作を変更するための拡張機能を使用してレールのアプリです。

拡張機能を使用してコントローラにフィルタを追加することがあります(質問のサンプルコードなど)。 1つの使用例は、静的コンテンツ拡張である。

静的コンテンツ拡張機能を使用すると、指定した要求パスに対して、データベースに格納されたHTMLページを表示して表示することができます。たとえば、デフォルトのコンテンツの代わりにこれらのHTMLページの1つを表示することができます。

静的コンテンツ拡張機能は、すべての要求をフィルタリングし、パスをチェックします。パスがdb内のページのいずれかと一致する場合、フィルタはページをレンダリングします。

静的コンテンツの拡張子は次のようにそのフィルタを宣言していますので:

Spree::BaseController.class_eval do 
    before_filter :render_page_if_exists 

    def render_page_if_exists 
    ... 
    end 
end 
+0

詳細は有用であろう。 – jonnii

+0

*少し*詳細を追加しました。私が助けるために追加できるものは何ですか? –

+0

私はその理由にもっと興味があります。 – jonnii

答えて

0

戻るRailsの1.0のフィルタチェーンは、次のようにキャッシュされて取得するので、問題はなかっただろう使用されていませんでした。

フィルタチェーンがキャッシュされた理由はパフォーマンスのためです。キャッシュしない理由はほとんどありません。それを動的にしたいと思っている人たちの周りを探索することから、私は1つの投稿しか見つけられませんでした。したがって、あなたがこのようなケースを得ない限り、アプリケーションが起動した後、フィルタチェーンが動的であるか再ロード可能である必要はほとんどないようです。

これを念頭に置いて、私はFilterChain.reloadのようなメソッドがパフォーマンスの向上を維持する良い方法だと思います。

Spree FilterChain.reloadは、拡張機能を読み込んだ後で呼び出すことができます。以前のコメント(before_filterのパッチ)で示唆した解決策のほうが、Railsコアに役立つ優れたショットがあると思います。

FilterChain.class_eval do 

    # Reloads all filter chains on all controllers, working from the ApplicationController down 
    # through the class hierarchy. e.g. Spree::BaseController would get its filter chain reloaded 
    # before its subclasses like ProductsController. We do this as ProductsController's filter chain 
    # relies on a copy of the Spree::BaseController filter chain. 
    def self.reload 
    # ApplicationController.filter_chain does not need reloading, it will be the only correct 
    # filter chain for sure as it is not inherited from a superclass. 
    reload_child_filter_chains(ApplicationController) 
    end 

    def self.reload_child_filter_chains(controller_class) 
    controller_class.immediate_subclasses.each do |controller_child| 
     # Reload filter chain on each controller who's immediate parent is the controller_class 
     controller_child.filter_chain.merge_filter_chain(controller_class.filter_chain) 
     # Reload the children of controller_child 
     reload_child_filter_chains(controller_child) 
    end 
    end 

    # New instance method on FilterChain to merges the given parent chain into itself. 
    def merge_filter_chain(parent_chain) 
    # Compare self and parent_chain and insert any parent_chain filters that 
    # are missing from self. You may need special handling for 
    # Filters that were marked for skipping or with :only, etc. conditions. 
    ... 
    end 
end 

はここのコメントから撮影:あなたが達成しようとしているもので

Spree issue 653 Specifying filters in extensions can create filter chains missing filters

関連する問題