我的主应用程序的应用程序控制器中有一个before_filter挂钩,它执行以下操作:(它不只是在闪存中放置一个链接,有一条消息,但它与问题无关,它只是访问方法中的路线)
class ApplicationController < ActionController::Base
before_filter :set_link
def set_link
flash[:notice] = items_path
end
end
这适用于应用程序,但是当我进入控制器获取引擎时,我得到了异常
No route matches {:controller=>"items", :action=>"index"}
据我所知,在引擎中,除非前缀为main_app
将应用程序控制器中的方法更改为
def set_link
flash[:notice] = main_app.items_path
end
摆脱异常,但我真的不想这样做。是否有其他解决方案让引擎识别main_app路由?
编辑:
如果应用程序布局调用路径助手,也会发生这种情况。因此,如果引擎被设计为集成到main_app的布局中,那么这个问题也会在那里出现。
答案 0 :(得分:19)
可安装引擎设计为这样工作,即隔离主应用程序路径和引擎路径。
如果要合并两组路由,可以使用非隔离引擎。第一步是删除引擎定义中的isolated_namespace
方法调用:
module MyEngine
class Engine < Rails::Engine
isolate_namespace MyEngine # remove this line
end
end
第二步是转换my_engine/config/routes.rb
中的路线,你应该从这里开始:
MyEngine::Engine.routes.draw do
# stuff that routes things
end
到此:
Rails.application.routes.draw do
# stuff that routes things
end
并删除应用程序路由中的mount
方法调用:
App::Application.routes.draw do
mount MyEngine::Engine => "/engine" # remove this line
end
这样做的主要好处是:
无需猴子补丁。我知道设计会做到这一点,但这可能是轨道中不存在引擎的日子。
无需在应用程序路径中安装引擎。另一方面,如果您想要更准确地控制插入点,这可能会适得其反,因为所有引擎路线将在您的主要路线之后(或之前,我没有这个问题的答案)被调用。
如果您正在寻找引擎上的文档,rails docs for the Engine class是一个非常好的起点。如果您对该主题感兴趣,我强烈建议您阅读它们(如果您还没有)。
答案 1 :(得分:4)
我想出了如何做到这一点。问题在于孤立的命名空间。为了将引擎与应用程序集成并共享相同的布局(可能有来自主应用程序的路径助手),我这样做了:
首先,我从引擎中删除了config/routes.rb
然后我从引擎类
中删除了isolate_namespacemodule MyEngine
class Engine < Rails::Engine
- isolate_namespace MyEngine
end
end
end
我添加了一个加载到引擎中的文件:
module ActionDispatch::Routing
class Mapper
def mount_my_engine_at(mount_location)
scope mount_location do
#Declare all your routes here
end
end
end
end
最后,在主应用config/routes.rb
而不是'挂载'引擎中,您可以调用您的方法
mount_my_engine_at "mount_location"
这将基本上“装载”您的引擎作为主应用程序的一部分,而不是与它隔离。它类似于Devise的做法。
答案 2 :(得分:2)
您可以保留isolate_namespace。 在你的引擎routes.rb
MyEngine::Engine.routes.draw do
...
root to: "something#index"
end
Rails.application.routes.draw do
get "something", to: "my_engine/something#index"
end
然后在主应用程序routes.rb
Rails.application.routes.draw do
mount MyEngine::Engine => "/anything_you_want"
root to: "main#index"
end
通过这种方式,您可以选择要公开的路线(以及您不想要的路线)
答案 3 :(得分:0)
最简单的方法是在主应用程序和引擎中绘制路径,以便两者都可以访问它们:
[MyEngine::Engine, App::Application].each do |app|
app.routes.draw do
# Declare all your routes here
end
end
答案 4 :(得分:0)
您可以保留Rails Engine指南强烈建议的isolate_namespace,并执行以下操作:
# inside your main_app's config/routes.rb
Rails.application.routes.draw do
root to: 'home#index'
mount MyEngine::Engine, at: "/"
end
# inside your engine's controller
module MyEngine
class SomeController << ::ApplicationController
# include main_app's route helpers
helper Rails.application.routes.url_helpers
end
end
在您的gem内,确保所有url辅助程序都以正确的路由代理方法(例如my_engine.pages_path)为前缀。
您的main_app的布局和引擎的控制器将正确地路由并链接到这些url帮助器并链接到主应用程序。您无需在主应用程序的任何位置添加“ main_app”前缀。唯一的缺点是您要在main_app的根路径上安装引擎的路由,这可能与同名的任何路由发生冲突。无论如何,如果您要执行非isolate_namespace,这都是可以预期的。