Extend ActionController::Base from a Rails 4 engine

715 views Asked by At

I am trying to extend the ActionController::Base from a rails 4 engine, so that any app that mounts it runs a specific method before each action. Now I understand there might be several different ways to do this, like concerns, class_eval or open classing it, but I am quite new at all of this and the links I could find were mostly about how to extend engine controllers from the main app, not the way around like I am trying to.

This is what I have tried, I've created a new folder in the controllers folder of my engine as follow:

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

and in the base_controller.rb I've added the following:

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

this doesn't work. I thought it would be because it was not being loaded (I am still trying to understand how and where to place custom code like this in a rails engine), so I tried to copy that code to the my_engine/lib/my_engine/engine.rb file but then I get the following error when starting the server:

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

How can accomplish this, and where should I place the files correctly?

1

There are 1 answers

0
blelump On BEST ANSWER

It can be easily achieved from within engine Engine class, e.g:

class Engine < ::Rails::Engine

  ActionController::Base.class_eval do

     include Some::Module

  end

end

This approach however implies that any change in Some::Module needs server restart to load that change. It might be annoying so perhaps using simple OOP inheritance would solve that even better.

In this case engine will provide some controller with logic, lets call it EngineController. Now, the controllers hierarchy would look like:

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