Rails可安装发动机并覆盖另一个发动机

时间:2012-06-29 09:47:17

标签: ruby-on-rails devise override rails-engines actionview

我正处于将标准Rails应用程序转换为可安装引擎的过程中。该应用程序可与标准博客应用程序相媲美,我希望每个模型,控制器和视图都可以扩展,因此我选择了可​​安装的引擎。

我使用的宝石之一是Devise,据我所知,这是一种可安装的引擎本身。它可以在here所述的可安装引擎内使用。

我可以在我的引擎中部分使用它。一切都工作正常,包括一些Devise控制器我覆盖像这样:

# 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
  ...

正确的视图'views / bbronline / devise_overrides / registrations / new_intermediair.html.haml'也按预期正确加载。

但是我的问题是我没有自定义控制器覆盖的视图没有正确加载。例如,登录视图应位于views/bbronline/devise/sessions/new.html.haml且未加载的视图。而是加载标准的Devise登录视图,即devise-2.1.0/app/views/devise/sessions/new.html.erb

当然,我可以通过使用我自己的控制器覆盖每个控制器来解决这个问题,就像上面的registrations_controller一样,但这看起来非常难看。是否覆盖每个控制器的方式?是否有更方便的方法从另一个可安装的引擎中覆盖可安装引擎的视图?

3 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分:4)

view_paths的顺序不正确。检查Devise :: SessionsController的视图路径显示:

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]> 

可安装引擎的最后一条路径应该位于中间路径之前。解决方案是在application.rb中设置加载优先级,如下所示:

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

rails api中也记录了这一点:http://api.rubyonrails.org/classes/Rails/Engine.html#label-Loading+priority

感谢JoséValim指出正确的方向。

答案 2 :(得分:1)

我需要更多信息。您定义了哪个控制器以及它从哪个控制器继承?正在渲染哪个视图以及您希望渲染哪个视图?此外,.view_paths是您的朋友,请尝试以下操作:

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

这将使您更好地了解每个控制器搜索模板的位置。