【问题标题】:Engine routes in Application Controller应用程序控制器中的引擎路由
【发布时间】:2011-09-28 19:58:18
【问题描述】:

我的主应用程序的应用程序控制器中有一个 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 的布局中,那么这个问题也会在那里出现。

【问题讨论】:

  • main_app 有什么问题?除此之外,为什么您要从主应用程序中引入引擎依赖项,这样您的引擎依赖于在 每个 使用它的应用程序中定义的items_path。这不是一个好的做法,通常您应该只使用main_app.root_path,或其他一些众所周知的路线(例如,如果您使用设计sign_in_path)。
  • items_path 将在已构建的主应用程序中定义。我希望将引擎安装在某个地方,但集成到当前应用程序的布局中。引擎本身根本不会引用 items_path。我只想将引擎生成的视图放入应用程序布局的主体中。但是应用布局需要访问main_app的路由
  • 这是因为需要让引擎和应用程序共享相同的布局。这样,当用户从主应用程序上的页面转到引擎上的页面时,布局之间没有明显的差异。

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


【解决方案1】:

可挂载引擎就是这样设计的,即隔离主应用路由和引擎路由。

如果要合并两组路由,可以使用非隔离引擎。第一步是删除引擎定义中的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

这样做的主要优点是:

  1. 无需猴子修补导轨。我知道 devise 会这样做,但这可能是在 Rails 中不存在引擎的日子里遗留下来的。

  2. 无需在应用程序路径中安装引擎。另一方面,如果您想更精确地控制插入点,这可能会适得其反,因为您的所有引擎路线都将在您的主要路线之后(或之前,我没有这个问题的答案)被调用。

如果您正在寻找有关引擎的文档,rails docs for the Engine class 是一个很好的起点。如果您对该主题感兴趣,我强烈建议您阅读它们(如果您还没有的话)。

【讨论】:

  • 您忘记注意了,如果您删除 isolated_namespace,您可能会遇到与主应用程序或其他 gem 的名称冲突(例如:助手)
【解决方案2】:

我想出了如何做到这一点。问题在于隔离的命名空间。为了将引擎与应用程序集成并共享相同的布局(可能有来自主应用程序的路径助手),我这样做了:

首先我从引擎中删除了config/routes.rb

然后我从引擎类中删除了isolate_namespace

module 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 的做法。

【讨论】:

    【解决方案3】:

    你可以保留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
    

    通过这种方式,您可以选择要公开的路线(以及不公开的路线)

    【讨论】:

      【解决方案4】:

      您可以按照 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,这无论如何都是意料之中的。

      【讨论】:

        【解决方案5】:

        最简单的方法是在主应用和引擎中绘制路线,以便两者都可以访问:

        [MyEngine::Engine, App::Application].each do |app|
          app.routes.draw do
            # Declare all your routes here
          end
        end
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-09-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多