有没有办法强制before_filter始终执行最后一次?

时间:2009-07-13 09:20:51

标签: ruby-on-rails

我想在控制器中定义一个before_filter,但总是让它最后执行。

我知道append_before_filter,但是我想在一个模块中指定这个过滤器,其他类也可以在以后添加其他的before_filters。

有没有办法做到这一点?

4 个答案:

答案 0 :(得分:3)

这是一个简单的模块,允许在完整的before_filters集之后执行任意代码。通过一些工作,您可以清理它,以便在此处执行特殊after_before_filters的队列(具有适当的暂停行为,等等)。

module OneLastFilterModule

  def self.included(base)
    base.class_eval do

      def perform_action_without_filters_with_one_last_filter

        #
        # do "final" before_filter work here
        #

        perform_action_without_filters_without_one_last_filter
      end
      alias_method_chain :perform_action_without_filters, :one_last_filter

    end
  end

end

请注意,您应该小心这样做,因为控制器本身可能会根据声明顺序对过滤器排序做出假设。

答案 1 :(得分:2)

我不知道实现这一目标的优雅方式。但是,使用一些横向思维......你可以确保你的所有控制器都使用prepend_before_filter。这样,如果您的模块使用before_filter,您将知道它将始终是最后一个过滤器,因为控制器将始终将其过滤器添加到过滤器链的开头。

答案 2 :(得分:2)

您可以覆盖模块中的before_filter,或让self.included回调挂钩声明alias_method_chain :before_filter, :final_filter。对于您希望能够移植到多个版本的Rails的代码,或者您将发布要在其他上下文中使用的代码,建议不要这样做。

答案 3 :(得分:1)

根据rails API,默认的“before_filter”是“append_before_filter”的别名,它将过滤器附加到filter_chain列表的末尾。我会说有一个合理的假设,如果你在控制器中正确地命令过滤器,它们将被按顺序执行。如前面的答案所示,还有一个“prepend_before_filter”可确保您添加的过滤器位于filter_chain的前面。