Rails 从主应用程序路由时未找到可安装引擎辅助方法
Rails mountable engines helper methods not found when routing from main app
我有一个模块作为安装到主应用程序的可安装引擎
通过
mount MyEngine::Engine, :at => '/myengine'
我在 negine 中为所有内容命名空间,引擎在 engine/app/views/myengine/
中有自己的视图
当我 运行 rails 服务器然后尝试访问
时一切正常
localhost:3000/myengine
首先,然后转到主应用程序的根目录,然后通过主应用程序索引视图中的 link 返回引擎
然而,当我启动服务器时,转到 localhost:3000 并从那里单击 link 到引擎模块,它会尝试正确获取视图,但是引擎助手中包含的方法引发调用它们未定义时出错。
我在 rails 4
您需要在 lib/engine.rb
文件中明确包含助手:
initializer 'your-gem-name.setup_helpers' do |app|
app.config.to_prepare do
ActionController::Base.send :include, HelperModuleName
end
end
end
我使用 eager_load 加载可安装引擎,它已在主应用程序中初始化,现在一切似乎都在工作。
Myengine::Engine.eager_load!
我也 运行 关注这个问题。我在我的引擎中定义了一个 ApplicationController
,当我试图在我的引擎的一个控制器中使用辅助方法时,我看到了 NoMethodError
s。
问题
代码看起来像这样:
在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 的 link,我会得到一个 NoMethodError
说 translations_include_tag
不存在。
解释
我认为发生这种情况是因为该应用程序有两个同名的 类:MyEngine
中的 ApplicationController
和主机应用程序中的 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
的 ApplicationController
:
来解决问题
在my_engine/app/controllers/my_engine/projects_controller.rb
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
内命名的,所以它的全名是 MyEngine::ApplicationController,与主应用程序的 ApplicationController
不冲突,因为常量名称不同。
我有一个模块作为安装到主应用程序的可安装引擎 通过
mount MyEngine::Engine, :at => '/myengine'
我在 negine 中为所有内容命名空间,引擎在 engine/app/views/myengine/
中有自己的视图当我 运行 rails 服务器然后尝试访问
时一切正常localhost:3000/myengine
首先,然后转到主应用程序的根目录,然后通过主应用程序索引视图中的 link 返回引擎
然而,当我启动服务器时,转到 localhost:3000 并从那里单击 link 到引擎模块,它会尝试正确获取视图,但是引擎助手中包含的方法引发调用它们未定义时出错。
我在 rails 4
您需要在 lib/engine.rb
文件中明确包含助手:
initializer 'your-gem-name.setup_helpers' do |app|
app.config.to_prepare do
ActionController::Base.send :include, HelperModuleName
end
end
end
我使用 eager_load 加载可安装引擎,它已在主应用程序中初始化,现在一切似乎都在工作。
Myengine::Engine.eager_load!
我也 运行 关注这个问题。我在我的引擎中定义了一个 ApplicationController
,当我试图在我的引擎的一个控制器中使用辅助方法时,我看到了 NoMethodError
s。
问题
代码看起来像这样:
在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 的 link,我会得到一个 NoMethodError
说 translations_include_tag
不存在。
解释
我认为发生这种情况是因为该应用程序有两个同名的 类:MyEngine
中的 ApplicationController
和主机应用程序中的 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
的 ApplicationController
:
在my_engine/app/controllers/my_engine/projects_controller.rb
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
内命名的,所以它的全名是 MyEngine::ApplicationController,与主应用程序的 ApplicationController
不冲突,因为常量名称不同。