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'


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
    def prepend_front
       prepend_view_path "app/views/front"


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

3 answers

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.



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


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'



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')


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.



All Articles