【问题标题】:Running before filter in plugin. Is there any other way?在插件过滤器之前运行。还有其他方法吗?
【发布时间】:2025-12-02 21:15:02
【问题描述】:

我正在编写我的第一个插件,在那个插件中,我需要为一些控制器/动作对运行一个方法。对于这个插件,配置 yml 看起来像这样 -

track1:
   start_action: "home", "index"
   end_action: "user", "create"

所以,在我的插件中,我将首先阅读上面的 yml 文件。之后,我想运行一个动作,例如 - first_function as before_filter 到 home-controller index-action ,我将运行 second_function 作为 after_filter 用于 user-controller create-action。

但我不知道如何为此编写过滤器,它将在插件中声明,并将针对用户在上述 yml 文件中指定的操作运行。

请帮忙!

【问题讨论】:

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


    【解决方案1】:

    我看到了实现目标的两种选择。

    第一种方法:在 ApplicationController 中声明两个过滤器,并在过滤器中检查 controller_nameaction_name 是否与您的 yaml 配置中的任何匹配。如果它们匹配,则执行它,如果不忽略。

    在想要的代码中

    class ApplicationController
    
      before_filter :start_action_with_check
      after_filter :end_action_with_check
    
      def start_action_with_check
        c_name, a_name = CONFIG['track1']['start_action'].split(', ')
        if c_name == controller_name && a_name == action_name 
          do_start_action
        end
      end
    
      ...
    

    希望你能明白。

    第二种方法:定义before_filter 的一种简洁方法是在模块中定义它们。通常你会使用self.included 方法来定义before_filter,当然你也可以有条件地定义它们。例如:

    class HomeController < ApplicationController
    
      include StartOrEndAction
    
      ...
    end
    

    lib/start_or_end_action.rb 你写

    module StartOrEndAction
    
      def self.included(base)
        # e.g. for the start-action        
        c_name, a_name CONFIG['track1']['start_action'].split(', ')
        if c_name == controller_name && a_name == action_name 
          base.before_filter :do_start_action
        end
        # and do the same for the after_filter
      end
    
      def do_start_action
        ...
      end
    
      def do_end_action
        ...
      end
    end 
    

    第二种解决方案的优点是before_filterafter_filter 仅在需要时定义。缺点是您必须将模块包含到每个控制器中,您可以在其中配置前置过滤器。 第一个的优点是可以覆盖任何控制器,并且检查前后过滤器会产生一些开销。

    希望这会有所帮助。

    【讨论】: