2011-09-28 8 views
12

Ho un hook before_filter nel controller dell'applicazione della mia app principale che fa qualcosa del tipo: (Non si limita a mettere un link nel flash, c'è un messaggio, ma non è rilevante per il domanda, semplicemente accede al percorso nel metodo)Percorsi del motore in Application Controller

class ApplicationController < ActionController::Base 
    before_filter :set_link 

    def set_link 
    flash[:notice] = items_path 
    end 
end 

Questo funziona bene per l'applicazione, tuttavia quando vado in controllori per un motore che ho fatto ho eccezione

No route matches {:controller=>"items", :action=>"index"} 

capisco che quando si è nel motore, gli helper dei percorsi sono per il motore a meno che non sia prefisso d con main_app

Così cambia il metodo nel controller applicazione per

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

si libera l'eccezione ma davvero non voglio avere a che fare. C'è un'altra soluzione per far sì che il motore riconosca i percorsi main_app?

EDIT:

Questo accade anche se il layout applicazione chiama aiutanti di percorso. Quindi se il motore è stato progettato per essere integrato nel layout di main_app, anche questo problema verrà ritagliato.

+1

Cosa c'è di sbagliato in 'main_app'? Oltre a ciò, perché stai introducendo una dipendenza nel tuo motore dall'app principale, in questo modo il tuo motore dipende da 'items_path' che viene definito in ** ogni ** app che lo usa. Questa non è una buona pratica, di solito dovresti usare solo "main_app.root_path', o alcune altre rotte ben note (per esempio se stai usando il" sign_in_path "). – Fabio

+0

item_path verrebbe definito nell'app principale che è già stata creata. E voglio avere il motore montato da qualche parte ma integrato nel layout dell'app corrente. Il motore stesso non fa mai riferimento a items_path. Voglio solo che le viste generate dal motore vengano inserite nel corpo del layout dell'applicazione. Tuttavia, il layout dell'applicazione deve accedere alle route del main_app – Olives

+0

Ciò deriva dal fatto che il motore e l'applicazione condividono lo stesso layout. In questo modo quando un utente passa da una pagina dell'app principale a una pagina del motore, non vi è alcuna differenza visibile tra il layout. – Olives

risposta

18

I motori installabili sono progettati per funzionare in questo modo, ovvero isolano i percorsi principali delle app e le rotte del motore.

Se si desidera unire i due insiemi di rotte, è possibile utilizzare un motore non isolato.Il primo passo è la rimozione della chiamata isolated_namespace metodo nella definizione di motore:

module MyEngine 
    class Engine < Rails::Engine 
    isolate_namespace MyEngine # remove this line 
    end 
end 

Il secondo passo è quello di convertire i percorsi in my_engine/config/routes.rb, si dovrebbe andare da questo:

MyEngine::Engine.routes.draw do 
    # stuff that routes things 
end 

a questo:

e rimuovere la chiamata al metodo mount nei percorsi dell'applicazione:

App::Application.routes.draw do 
    mount MyEngine::Engine => "/engine" # remove this line 
end 

I principali vantaggi di fare in questo modo potrebbe essere:

  1. Non c'è bisogno di rotaie scimmia-di patch. So che concepire fa questo, ma questo potrebbe essere un residuo dei giorni in cui i motori non esistevano nei binari.

  2. Non è necessario montare il motore nei percorsi dell'applicazione. D'altra parte, questo potrebbe ritorcersi contro se si desidera controllare con maggiore precisione il punto di inserimento in quanto tutti i percorsi del motore saranno chiamati dopo (o prima, non ho la risposta a questa domanda) i percorsi principali.

Se siete alla ricerca di documentazione sui motori, il rails docs for the Engine class sono un buon punto di partenza. Consiglio vivamente di leggerli (nel caso non l'hai ancora) se sei interessato all'argomento.

+0

Oh uomo grazie, mi stavo strappando i capelli ... –

+0

hai dimenticato di notare, se togli il 'isolated_namespace' potresti esporsi a qualche conflitto di nomi con l'app principale o altre gemme (esempio: helper) – montrealmike

+0

Can not inversalo di più! – Nerve

4

Ho capito come fare. I problemi si trovano nello spazio dei nomi isolato. Al fine di integrare il motore con l'applicazione e condividere lo stesso layout (che può avere aiutanti percorso dal app principale) ho fatto questo:

In primo luogo ho rimosso config/routes.rb dal motore

Poi ho tolto l'isolate_namespace da la classe di motori

module MyEngine 
    class Engine < Rails::Engine 
- isolate_namespace MyEngine 
    end 
end 
end 

ho aggiunto un file che è stato caricato nel motore:

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 

Infine, nella principale app config/routes.rb invece di 'mount'ing del motore, è possibile chiamare il metodo

mount_my_engine_at "mount_location" 

Questo sarà essenzialmente 'montare' il motore come parte della app principale invece di essere isolati da esso. È simile a come lo fa anche Devise.

0

Il modo più semplice è quello di disegnare i percorsi, sia l'applicazione principale, e il motore, in modo che siano accessibili a entrambi:

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

È possibile mantenere l'isolate_namespace. nel tuo motore di 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 

E poi nel l'applicazione principale routes.rb

Rails.application.routes.draw do 

    mount MyEngine::Engine => "/anything_you_want" 

    root to: "main#index" 
end 

In questo modo è possibile scegliere quali percorsi si desidera esporre (e che non lo fanno)

Problemi correlati