从主应用程序路由时找不到Rails可安装引擎辅助方法

时间:2015-06-23 17:14:57

标签: ruby-on-rails ruby rails-engines

我有一个模块作为可安装引擎安装到主应用程序 通过

mount MyEngine::Engine, :at => '/myengine'

我将所有内容命名为negine,并且引擎在engine / app / views / myengine /

中拥有自己的视图

当我运行rails服务器然后尝试访问

时,一切正常
  

本地主机:3000 / myengine

首先转到主应用程序的根目录,然后通过主应用程序索引视图中的链接返回引擎

然而,当我启动服务器时,转到localhost:3000并从那里单击指向引擎模块的链接,它尝试正确地获取视图但是引擎的助手中包含的方法在调用时引发错误因为他们没有被定义。

我在轨道4

3 个答案:

答案 0 :(得分:1)

我使用eager_load加载可安装的引擎,它在主应用程序中初始化,现在一切似乎都在运行。

Myengine::Engine.eager_load!

答案 1 :(得分:1)

我也碰到了这个问题。我在引擎内部定义了一个ApplicationController,并且在尝试在引擎的一个控制器中使用辅助方法时看到了NoMethodError

问题

代码看起来像这样:

在my_engine / app / controllers / my_engine / application_controller.rb

module MyEngine
  class ApplicationController < ActionController::Base
    helper ApplicationHelper
  end
end

在my_engine / app / controllers / my_engine / projects_controller.rb

module MyEngine
  class ProjectsController < ApplicationController
    def new
      # some action code here
    end
  end
end

在my_engine / app / helpers / my_engine / application_helper.rb

module MyEngine
  module ApplicationHelper
    def translations_include_tag
      javascript_include_tag "translations-#{I18n.locale}.js"
    end
  end
end

如果我在主机rails应用程序中导航至某个路线,然后单击导航至my_engine / projects / new的链接,我将得到NoMethodErrortranslations_include_tag不存在。

说明

我认为发生这种情况是因为该应用程序有两个具有相同名称的类:ApplicationController中的MyEngine和宿主应用程序中的ApplicationController。当访问引擎外部的第一条路线时,Rails会从主机应用程序自动加载ApplicationController。这意味着Rails将主应用程序的ApplicationController与名称“ ApplicationController”相关联。当您导航到my_engine / projects / new时,Rails延迟加载ProjectsController,它也继承自ApplicationController。 Rails / ruby​​认为您指的是已经加载的 same ApplicationController,因此实际上ProjectsController最终是从主机应用程序的ApplicationController继承而来的引擎中的那个。由于主机应用程序的translations_include_tag中没有定义ApplicationController方法,因此当视图试图调用它时,ruby会引发NoMethodError

解决方案

我能够通过显式继承MyEngine的{​​{1}}来解决此问题:

在my_engine / app / controllers / my_engine / projects_controller.rb

ApplicationController

解决继承问题后,module MyEngine # changed from just plain 'ol ApplicationController class ProjectsController < ::MyEngine::ApplicationController def new # some action code here end end end 消失了。

公认的答案是使用紧急加载,这也将解决此问题,因为它会强制首先加载引擎的NoMethodError。由于引擎的ApplicationController是在ApplicationController中命名的,它的全名是MyEngine :: ApplicationController,它与主应用程序的MyEngine没有冲突,因为常量名是不同的。

答案 2 :(得分:0)

您需要在lib/engine.rb文件中明确包含帮助程序:

initializer 'your-gem-name.setup_helpers' do |app|
    app.config.to_prepare do
      ActionController::Base.send :include, HelperModuleName
    end
  end
end