2012-02-14 41 views
34

假設我有一個基本的控制器一些邏輯將信息傳遞給視圖建立的東西像一個麪包屑:過濾器在渲染之前但在控制器之後執行?

class ContextAwareController < ApplicationController 

    after_filter :build_breadcrumb 

    def build_breadcumb 
    #... 
    end 
end 

我想這build_breadcrumb方法主控制器邏輯後運行,但以前視圖被渲染。

上述代碼運行得太晚,但before_filter會太早。

任何人都可以建議的方式來實現這一點,而不在每個子控制器的行動結束顯式調用build_breadcumb?

感謝

回答

2

我相信渲染開始時呈現被調用,而且也沒有默認的方式推遲它。您可以執行以下一項操作:

過濾器以聲明的相同順序應用。因此,讓第二個後置過濾器調用渲染,並將數組參數存儲在類變量中。然後,任何你通常會調用渲染的地方,設置變量。

49

我有同樣的問題,解決它像這樣:

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

但是這種解決方案會減慢每個渲染速度。 – freemanoid 2013-06-04 13:10:52

+1

它只會減慢從特定控制器製作的渲染速度。將它移動到不同的控制器或「子控制器」是很容易的,這樣只有需要麪包屑的動作才能使用此版本的「render」。 – Jon 2013-07-08 14:59:16

+0

我們也可以使用一個控制器來關注添加此功能選擇 http://elegantbrew.tumblr.com/post/70990048275/controller-concerns-in-rails-4 – MhdSyrwan 2016-01-08 14:28:41

2

也有一些寶石來實現這一目標。其中之一是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 2013-02-12 12:04:48

-1

你可以這樣做,以假一before_render:

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 

感謝@joshua -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 
相關問題