2011-09-28 59 views
12

我在我的主應用程序的應用程序控制器中有一個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"} 

我明白當在引擎中時,路由助手是引擎的前綴,除非是前綴d與main_app

因此改變應用控制器的方法

def set_link 
    flash[:notice] = main_app.items_path 
    end 

擺脫了異常,但我真的不希望有這樣做。是否有另一種解決方案讓引擎識別main_app路線?

編輯:

如果應用程序佈局調用路徑助手,也會發生這種情況。所以如果引擎被設計成集成到main_app的佈局中,那麼這個問題也會在那裏出現。

+1

'main_app'有什麼問題?除此之外,爲什麼你從主應用程序在引擎中引入了一個依賴項,這樣你的引擎就依賴於在每個使用它的**應用程序中定義的items_path。這不是一個好習慣,通常你只應該使用'main_app.root_path'或其他一些衆所周知的路由(例如,如果你使用'sign_in_path')。 – Fabio

+0

items_path將在已經構建的主應用程序中定義。我想將引擎安裝在某個位置,但集成到當前應用程序的佈局中。引擎本身從不引用items_path。 我只想將引擎生成的視圖放入應用程序佈局的主體中。但是,應用程序佈局需要訪問main_app的路線 – Olives

+0

這需要讓引擎和應用程序共享相同的佈局。這樣當用戶從主應用程序中的頁面轉到引擎上的頁面時,佈局之間沒有明顯的區別。 – Olives

回答

18

可安裝引擎的設計工作就是這樣,即隔離主要應用程序路線和引擎路線。

如果您希望合併兩組路線,您可以使用非隔離引擎。第一步是在你的引擎定義中刪除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. 無需猴子補丁軌道。我知道設計這樣做,但這可能是引擎不存在於導軌中的那段時間剩下的。

  2. 無需在應用程序路徑中安裝引擎。另一方面,如果您希望更精確地控制插入點,因爲所有引擎路由將在您的主要路徑之後(或之前,我沒有這個問題的答案)被調用。

如果您正在尋找在發動機上的文件,該rails docs for the Engine class是一個很好的起點。如果你對這個主題感興趣,我強烈建議你閱讀它們(如果你還沒有的話)。

+0

哦,男人謝謝,我把我的頭髮拉出來...... –

+0

你忘了說明,如果你刪除'isolated_namespace'你可能會暴露自己與主應用程序或其他寶石的名稱衝突(例如:助手) – montrealmike

+0

Can not upvote它更多! – Nerve

4

我想出瞭如何做到這一點。問題在於孤立的命名空間。爲了將發動機的應用集成和共享相同的佈局(可能有從主應用程序路徑傭工)我這樣做:

首先我刪除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'ing引擎,你可以打電話給你的方法

mount_my_engine_at "mount_location" 

這基本上會‘裝’你的引擎作爲主要的應用程序,而不是從它被孤立的一部分。這與Devise的做法很相似。

0

最簡單的方法是繪製在兩個主要的應用程序,並且發動機的途徑,使他們都可以訪問:

[MyEngine::Engine, App::Application].each do |app| 
    app.routes.draw do 
    # Declare all your routes here 
    end 
end 
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 

這種方式,你可以選擇你想要的路線暴露(和你不這樣做)