2012-02-14 69 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