A common task after including Engine in your Rails app is extending some classes (models, controllers, other classes) defined in the Engine.
It can be done using Decorator pattern.
There are two options of extending a class defined in Engine:
- use Class@class_eval
- use ActiveSupport::Concern
For simple class modifications, use Class#class_eval.
For complex class modifications, consider using ActiveSupport::Concern.
Read more in Rails guides.
# lib/myengine/engine.rb
module Myengine
class Engine < ::Rails::Engine
isolate_namespace Myengine
config.to_prepare do
Dir.glob(Rails.root + "app/decorators/**/*_decorator*.rb").each do |c|
require_dependency(c)
end
end
end
endin the Engine:
# Blorgh/app/models/article.rb
class Article < ActiveRecord::Base
has_many :comments
def summary
"#{title}"
end
endin the main app:
# MyApp/app/decorators/models/blorgh/article_decorator.rb
Myengine::Article.class_eval do
# add new method
def time_since_created
Time.current - created_at
end
# override the method
def summary
"#{title} - #{truncate(text)}"
end
endWe have a class defined in Engine:
# myengine/lib/myengine/mymodule/myclass.rb
module Myengine
module Mymodule
class Myclass
include Optimacms::Concerns::AdminMenu::AdminMenu
end
end
end
Add concern to Engine:
# myengine/lib/concerns/mymodule/myclass.rb
module Optimacms::Concerns::AdminMenu::AdminMenu
extend ActiveSupport::Concern
included do
end
def my_object_method
'it is engine'
end
module ClassMethods
# will be overridden in the main app
def my_class_method
[]
end
end
end
Use concern in the main app:
# myapp/lib/myengine/mymodule/myclass.rb
module Myengine
module Mymodule
class Myclass
include Optimacms::Concerns::AdminMenu::AdminMenu
# override class method
def self.my_class_method
['1', '2', '3']
end
# override object method
def my_object_method
'this is app'
end
end
end
end