如何在Rails3应用程序中的所有其他控制器before_filters之后在gem中追加before_filter?

Paw*_*cki 9 ruby gem ruby-on-rails ruby-on-rails-3

有一个宝石,它附加一个before_filter到Rails应用程序:

class Railtie < Rails::Railtie
  initializer "..." do
    ActiveSupport.on_load(:action_controller) do
      ActionController::Base.send(:include, Filter)

...

module Filter
  extend ActiveSupport::Concern

  included do
    append_before_filter :set_locale
  end

  def set_locale
     ....
Run Code Online (Sandbox Code Playgroud)

这里是应用程序中的一些控制器:

class DesktopsController < ApplicationController
  before_filter :set_language_in_session
Run Code Online (Sandbox Code Playgroud)

现在问题在于,before_filter来自gems的是在before_filter来自DesktopsController 之前的过滤器链中:

DesktopsController._process_action_callbacks.select { |c| c.kind == :before }.collect { |filter| filter.filter }
=> [
    [0] :set_locale,
    [1] :set_language_in_session
]
Run Code Online (Sandbox Code Playgroud)

我怎样才能使before_filter从宝石(set_locale)放所有其他过滤器?秘密可能在于这一行:

ActiveSupport.on_load(:action_controller) do
Run Code Online (Sandbox Code Playgroud)

但我尝试了不同的图书馆,没有任何运气......

顺便说一句.这是宝石的完整代码.Ruby 1.9.2,Rails 3.0.5.

nat*_*vda 3

调整宝石永远不会起作用。gem 被初始化为 Rails 过程中的首要任务之一,因此在任何实际控制器启动之前。所以这意味着,无论你做什么,宝石的过滤器很可能仍然是第一个宝石。

所以我看到的唯一解决方案是:

  • 在您自己的控制器中使用prepend_before_filter那些需要在set_locale.
  • 如果您需要显式控制,请使用skip_before_filter和explicit before_filter

在 Rails 2 应用程序中,我们设计了一个 hack,通过覆盖perform_action_without_filters(请参阅是否有方法强制 before_filter 始终最后执行?)来确保某些过滤器作为最后一个过滤器运行,但我们在升级到 Rails 3 时删除了它。