从Rails 4引擎扩展ActionController :: Base

时间:2014-11-13 17:25:15

标签: ruby-on-rails ruby rails-engines activesupport-concern

我正在尝试从rails 4引擎扩展ActionController::Base,以便任何安装它的应用程序在每个操作之前运行特定方法。现在我明白可能有几种不同的方法可以做到这一点,例如关注点,class_eval或者对它进行开放式分类,但是我对这一切都很新,我能找到的链接主要是关于如何扩展引擎控制器主应用程序,而不是像我想要的那样。

这是我尝试过的,我已经在我的引擎的controllers文件夹中创建了一个新文件夹,如下所示:

my_engine
  |-- app
        |-- controllers
              |-- action_controller
                  |-- base_controller.rb
              |-- my_engine
                  |-- some_controller.rb
                  |-- other_controller.rb

并在base_controller.rb我添加了以下内容:

require_dependency "action_controller/base"

module ActionController
  class BaseController

    before_action :some_method

    private
    def some_method
      #just for testing
      redirect_to 'http://www.google.com'
    end
  end
end

这不起作用。我认为这是因为它没有被加载(我仍然试图了解在rails引擎中如何以及在何处放置这样的自定义代码),所以我尝试将该代码复制到my_engine/lib/my_engine/engine.rb文件但是然后启动服务器时出现以下错误:

undefined method `before_action' for ActionController::BaseController:Class (NoMethodError)

如何做到这一点,我应该在哪里正确放置文件?

1 个答案:

答案 0 :(得分:2)

可以从引擎Engine类中轻松实现,例如:

class Engine < ::Rails::Engine

  ActionController::Base.class_eval do

     include Some::Module

  end

end

然而,这种方法意味着Some::Module中的任何更改都需要服务器重新启动才能加载该更改。它可能很烦人,所以使用简单的OOP继承可能会更好地解决这个问题。

在这种情况下,引擎会为某些控制器提供逻辑,让我们称之为EngineController。现在,控制器层次结构如下所示:

class EngineController < ActionController::Base; end # provided with an engine
class MainAppController < EngineController; end