简体   繁体   中英

Rails mountable engine and overriding another engine

I'm in the proces of converting my standard Rails app to an mountable engine. The app is comparable to a standard blogging app and i want every model, controller and view to be extendable hence my choice for a mountable engine.

One of the gems i use is Devise which is as far as i understand a sort of a mountable engine itself. It can be used inside a mountable engine as stated here .

I'm able to use it partially within my engine. Everything is working fine including some Devise controller i override like this one:

# config/routes.rb

Bbronline::Engine.routes.draw do
  devise_for :users, class_name: "Bbronline::User", module: :devise,
    controllers: { registrations: "bbronline/devise_overrides/registrations"}
    ...

# controllers/bbronline/devise_overrides/registrations_controller.rb
require_dependency "bbronline/application_controller"

module Bbronline

class DeviseOverrides::RegistrationsController < Devise::RegistrationsController

  def new_intermediair
    @user = User.new
  end
  ...

The correct view 'views/bbronline/devise_overrides/registrations/new_intermediair.html.haml' is also correctly loading as expected.

However my issue is that the views that i override without a custom controller are not properly loaded. For example the view that should the login view is located in views/bbronline/devise/sessions/new.html.haml and is not loaded. Instead the standard Devise login view gets loaded ie devise-2.1.0/app/views/devise/sessions/new.html.erb

Of course i could solve this problem by overriding every controller with my own controller like i did with the registrations_controller above but this seems very ugly. Is overriding every controller the way to do this? Is there a more convenient way to override views from an mountable engine from within another mountable engine?

如果您不想在使用引擎的每个应用程序中调整config.railties_order ,只需在lib \\ my_engine \\ engine.rb文件的顶部require 'devise'

The view_paths are in incorrect order. Checking the view paths of Devise::SessionsController shows:

Devise::SessionsController.view_paths 
=> #<ActionView::PathSet:0x007fa1bf0e36f8 @paths= [/Users/harmdewit/Dropbox/Code/projects/brightin/bbr-online/bbr-online-gem/test/‌​dummy/app/views, 
/Users/harmdewit/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/devise-2.1.‌​0/app/views, 
/Users/harmdewit/Dropbox/Code/projects/brightin/bbr-online/bbr-online-gem/app/vi‌​ews]> 

The last path of the mountable engine should come before the middle devise path. The solution is setting the loading priority in application.rb like this:

#test/dummy/config/application.rb (the app that uses my mountable engine)
...
config.railties_order = [Blog::Engine, :main_app, :all]
...

This is also documented in the rails api: http://api.rubyonrails.org/classes/Rails/Engine.html#label-Loading+priority

Thanks to José Valim for pointing in the right direction.

I need more information. Which controller are you defining and from which controller is it inheriting from? Which view is being rendered and which one did you expect to render? Also, .view_paths is your friend so try in your rails console the following:

Devise::SessionsController.view_paths
YourApp::SomeDeviseController.view_paths

This will give you a better idea of where each controller is searching for templates.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM