Skip to content

Instantly share code, notes, and snippets.

@trejo08
Created April 26, 2018 18:04
Show Gist options
  • Save trejo08/11df06b3c6ff8fa26c610447005b721f to your computer and use it in GitHub Desktop.
Save trejo08/11df06b3c6ff8fa26c610447005b721f to your computer and use it in GitHub Desktop.
How to add or overwrite methods from engine controllers or models in the app that uses the engine.
# This simple solution open-classes the controller/model in the main app
# to add or overwrite methods.
# A drawback of this solution is that you won't be able to access the original
# method by using +super+.
# engine: app/controllers/myengine/my_controller.rb
# This is the controller in our engine with a index method defined.
module MyEngine
class MyController < ApplicationController
def index
end
end
end
# app: app/controllers/myengine/my_controller.rb
# Now we open-class the engines controller in our app that uses the engine
# and overwrite the +index+ method.
# We need to require the engines controller first because Rails would only load
# the first controller it finds and that is our overwritten controller here.
require_dependency MyEngine::Engine.config.root.join('app', 'controllers', 'myengine', 'my_controller.rb').to_s
class MyEngine::MyController
def index
end
end
# Source
# http://stackoverflow.com/questions/7719633/how-to-extend-rails-engines-controllers-properly
# http://edgeguides.rubyonrails.org/engines.html#overriding-models-and-controllers
# A modification of this solution is using the decorator pattern. It also modifies
# the engine controller/model by open-classing but the extensions/overwrites
# are defined in another directory for example the lib directory.
# I don't like that pattern because I think it hides to modifications too much.
# Also the solution on edgeguides loads the decorators in the main app
# via initializer code in the engine. That feels weired for example
# ActiveAdmin places code in +app/decorators+ so now we would load that code
# twice...
# This solution creates a blank model/controller in the engine and adds all
# functionality via a concern. To overwrite or add methods in the main app
# you simply create the same blank model/controller, include the same module
# and define your overwrites.
# You can even use the original methods by calling +super+.
# engine: app/controllers/myengine/my_controller.rb
module MyEngine
class MyController < ApplicationController
include MyEngine::Concerns::Controllers::MyController
end
end
# engine: app/concerns/myengine/controllers/my_controller.rb
module MyEngine::Concerns::Controllers::MyController
extend ActiveSupport::Concern
def index
end
end
# app: app/controllers/myengine/my_controller.rb
module MyEngine
class MyController < ApplicationController
include MyEngine::Concerns::Controllers::MyController
def index
end
end
end
# Source
# http://edgeguides.rubyonrails.org/engines.html#overriding-models-and-controllers
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment