过滤器在渲染之前但在控制器之后执行?

时间:2012-02-14 17:15:19

标签: ruby-on-rails ruby ruby-on-rails-3

假设我在基本控制器中有一些逻辑将信息传递给视图以构建类似于痕迹的东西:

class ContextAwareController < ApplicationController

  after_filter :build_breadcrumb

  def build_breadcumb
    #...
  end
end

我希望这个build_breadcrumb方法在主控制器逻辑之后运行,但之前呈现视图。

上面的代码运行得太晚,但是before_filter太早了。

在没有在子控制器中的每个操作结束时显式调用build_breadcumb的情况下,是否可以建议一种方法来实现此目的?

由于

6 个答案:

答案 0 :(得分:52)

我遇到了同样的问题并解决了这个问题:

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

答案 1 :(得分:2)

我相信渲染在调用渲染时开始,并且没有默认的方法来推迟渲染。这是你可以做的一件事:

过滤器以声明的相同顺序应用。因此,制作第二个使用存储在类变量中的数组args调用render的后过滤器。然后在通常调用渲染的任何地方设置变量。

答案 2 :(得分: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

(从gem文档复制的代码剪辑)

答案 3 :(得分:2)

如果我们覆盖render,我们根本就没有真正使用过滤器链,因此确定我们使用{{1}时所采取的操作可能更为简单}}

@_action_name

答案 4 :(得分:0)

您可以像这样使用alias_method_chain

alias_method_chain :render, :before_render_action

这将创建2个方法:render_with_before_render_action:render_without_before_render_action。如果调用渲染,则将调用:render_with_before_render_action。您可以覆盖此方法

def render_with_before_render_action(*options, &block)
<your code>
render_without_before_render_action(*options, &block)
end

如果您不想执行代码,并且想要使用默认渲染,则应直接调用:render_without_before_render_action

答案 5 :(得分:-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

的提示