Rails prepend_view_path of the engine being mounted
In one hand I have a mountable engine let say Front The front contains my assets and a couple of pages It is isolated from the MainApp. I don't want it to touch the main application.
On the other hand, I want my MainApp to use the Front layout and partial interface. So I set up the layout this way:
class ApplicationController < ActionController::Base
layout 'front/application'
end
But the front end / attachment refers to the engine particle directly because of the insulation, for example
render 'header' # front/ prefix is not required
So MainApp views try to load app / views / application / header instead of app / views / front / application / header
To fix this, I put preend_view_path like this:
class ApplicationController < ActionController::Base
layout 'front/application'
before_filter :prepend_front
protected
def prepend_front
prepend_view_path "app/views/front"
end
end
But that doesn't work because the engine path points to the supplier. The engine will add it to the list of extra paths: ~ / main_app / vendor / private_gems / front-0.0.2 / app / views And my preprend_front method will create this: ~ / main_app / app / views / front
I tried to force add the correct path (but it looks so messy):
prepend_view_path "#{Rails.root}/vendor/private_gems/front-0.0.2/app/views/front"
I am not working, just the application crashing ...
And I'm stuck here. Maybe my design is wrong?
source to share
Finally, I remove the isolation property. I have moved my views one folder up, so from engine_app folders.
The only final adjustment was to include EngineApp :: Engine.url_helper in the MainApp application controller.
The preend stack looks like this:
- Main app path added
- Main types of applications
- Engine views
So, it is based on the engine and then adds the main application of the application at the top.
source to share
Jack's answer is perfect, except that you want to do this inside the Rails engine (for example, if your engine itself has "themes" that require a different loading path). In this case, the prepend_path and append_path are not appropriate because you want to insert your new load path before the default load path for engines, but after the application load path.
The solution to this (only tested in Rails 3.2) is to add the / lib / my _engine.rb file to your engine:
config.after_initialize do
my_engine_root = MyEngine::Engine.root.to_s
paths = ActionController::Base.view_paths.collect{|p| p.to_s}
paths = paths.insert(paths.index(my_engine_root + '/app/views'), my_engine_root + '/app/views/themes/my_theme')
ActionController::Base.view_paths = paths
end
The new loading path my_engine_root + '/app/views/themes/my_theme'
will now be just before your standard loading path for your enginemy_engine_root + '/app/views'
source to share
By default, Rails looks in the / views for a file, but when it doesn't find it, it looks in the / engine views. This means that you will need to add the path to the views so that Rails will look at the main application views / and then change the path in your engine and finally look at the engine /. Then it will be a stack:
- main types of applications /
- engine modified way (view / front / inner engine)
- engine views /
To do this go to application_controller.rb
class ApplicationController < ActionController::Base
before_filter :set_views_path
def set_views_path
append_view_path FnetIdentityRailsEngine::Engine.root.join('app', 'views', 'front')
end
end
If you have added your engine path to your view path, you will not be able to override engine views in the main application. This is why you want to add.
source to share