2012-02-14 7 views
34

は、私がパンくずのようなものを構築するためにビューに情報を渡すためにベースコントローラで、いくつかのロジックを持っていると仮定します。レンダリング前でコントローラの後に実行するフィルタ?

class ContextAwareController < ApplicationController 

    after_filter :build_breadcrumb 

    def build_breadcumb 
    #... 
    end 
end 

私は前後、メインコントローラロジックが、を実行するには、このbuild_breadcrumb方法をしたいですビューがレンダリングされます。

上記のコードは遅すぎますが、before_filterは早すぎます。

誰でも、子コントローラの各アクションの最後に明示的にbuild_breadcumbを呼び出さなくても、これを達成する方法を提案できますか?

おかげ

答えて

2

は、私が呼ばれたときにレンダリングを開始し、レンダリング信じ、それを延期するデフォルトの方法はありません。あなたができることの1つがあります:

フィルタは宣言​​された同じ順序で適用されます。ですから、クラス変数に格納された配列argsを使ってrenderを呼び出す2番目のafter-filterを作成してください。通常、レンダリングを呼び出す場所であれば、変数を設定します。

49

私は同じ問題を抱えていたし、このようにそれを解決:

class ApplicationController < ActionController::Base 
    def render *args 
    add_breadcrumbs 
    super 
    end 
end 
+2

しかし、この解決策はすべてのレンダリングを遅くします。 – freemanoid

+1

特定のコントローラから作成されたレンダリングを遅くするだけです。ブレッドクラムを必要とするアクションだけがこのバージョンの 'render'を使用するように、これを別のコントローラまたは"サブコントローラ "に移動するのは簡単です。 – Jon

+0

コントローラの懸念事項を使用して、この機能を選択的に追加することもできます http://elegantbrew.tumblr.com/post/70990048275/controller-concerns-in-rails-4 – MhdSyrwan

2

これを達成するためにいくつかの宝石でもあります。それらの1つはrails3_before_renderです。 それは、例えば、フィルタと同じように動作します:

class PostsController < ApplicationController 
    before_render :ping, :except => [:destroy] 

    def index; end 
    def new; end 
    def show; end 
    def destroy; end                   

    private 
    def ping 
     Rails.logger.info "Ping-Pong actions" 
    end 
end 

(コードは宝石のドキュメントからコピー切り取ら)

+3

このフィルタは、 _render_メソッドを呼び出すため、リダイレクトの可能性がある場合にbefore_renderをデータベース内のデータの更新に使用しないでください。 – knarewski

-1

あなたが偽のbefore_renderに次のように行うことができます。@joshuaへ

class StuffController < ApplicationController 
    before_filter :my_filter, only: [:index, :show] 

    def my_filter 
    @my_filter = true 
    end 
    def _my_filter 
    # Do the actual stuff here 
    end 
    def render(*args) 
    _my_filter if @my_filter 
    super 
    end 
end 

感謝-muheimの使い方についてrender

2

renderを上書きしている場合は、フィルタを実際に使用していません連鎖しているので、@_action_nameを使用してどの操作を行っているのかを簡単に判断できます。

StuffController < ApplicationController 

    def my_filter 
    # Do the stuff 
    end 

    def render(*args) 
    my_filter if @_action_name == "show" 
    super 
    end 

end 
関連する問題