2011-09-28 10 views
12

Tengo un gancho before_filter en el controlador de aplicaciones de mi aplicación principal que hace algo como: (No solo pone un enlace en el flash, hay un mensaje, pero no es relevante para el pregunta, simplemente accede a la ruta en el método) sin embargoRutas del motor en el Controlador de aplicación

class ApplicationController < ActionController::Base 
    before_filter :set_link 

    def set_link 
    flash[:notice] = items_path 
    end 
end 

Esto funciona bien para la aplicación, cuando voy a los controladores para un motor que hice consigo la excepción

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

entiendo que cuando están en el motor, las rutas auxiliares son para el motor a menos que prefixe d con main_app

tanto, cambiar el método en el controlador de aplicación a

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

se deshace de la excepción, pero realmente no quiero tener que hacer eso. ¿Hay alguna otra solución para que el motor reconozca las rutas main_app?

EDIT:

Esto también sucede si el diseño de la aplicación llama a ayudantes de ruta. Entonces, si el motor está diseñado para integrarse en el diseño de main_app, este problema también se verá afectado.

+1

¿Qué pasa con 'main_app'? Además de eso, por qué estás introduciendo una dependencia en tu motor desde la aplicación principal, de esta manera tu motor depende de que 'items_path' esté definido en ** cada ** aplicación que lo usa. Esta no es una buena práctica, por lo general debe usar 'main_app.root_path' u otras rutas bien conocidas (por ejemplo, si utiliza el' sign_in_path'). – Fabio

+0

items_path se definiría en la aplicación principal que ya está construida. Y quiero tener el motor montado en algún lugar, pero integrado en el diseño de la aplicación actual. El motor en sí nunca hace referencia a items_path. Solo quiero que las vistas generadas por el motor se coloquen en el cuerpo del diseño de la aplicación. Sin embargo, el diseño de la aplicación necesita acceder a las rutas de main_app – Olives

+0

Esto se debe a la necesidad de que el motor y la aplicación compartan el mismo diseño. De esta forma, cuando un usuario pasa de una página en la aplicación principal a una página en el motor, no hay una diferencia visible entre el diseño. – Olives

Respuesta

18

Los motores montables están diseñados para trabajar así, es decir, aíslan las rutas principales de las aplicaciones y las rutas del motor.

Si desea fusionar los dos conjuntos de rutas, puede utilizar un motor no aislado.El primer paso es la eliminación de la llamada isolated_namespace método en su definición del motor:

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

El segundo paso es convertir sus rutas en my_engine/config/routes.rb, debe pasar de esto:

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

a esto:

Rails.application.routes.draw do 
    # stuff that routes things 
end 

y elimine la llamada al método mount en las rutas de su aplicación:

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

Las principales ventajas de hacerlo de esta manera sería:

  1. No hay necesidad de carriles mono-parche. Sé que el diseño hace esto, pero esto podría ser un residuo de los días en que los motores no existían en los rieles.

  2. No es necesario montar el motor en las rutas de aplicación. Por otro lado, esto podría ser contraproducente si desea controlar con mayor precisión el punto de inserción, ya que todas las rutas de su motor se llamarían después (o antes, no tengo la respuesta a esta pregunta) sus rutas principales.

Si usted está buscando documentación sobre los motores, la rails docs for the Engine class son un buen punto de partida. Le recomiendo encarecidamente que los lea (en caso de que aún no lo haya hecho) si le interesa el tema.

+0

Oh, gracias, me estaba sacando el pelo ... –

+0

se te olvidó notar, si eliminas 'isolated_namespace' podrías exponerte a algunos conflictos de nombres con la aplicación principal u otras gemas (ejemplo: ayudantes) – montrealmike

+0

No se puede ¡lo votó más! – Nerve

4

Descubrí cómo hacerlo. Los problemas se encuentran dentro del espacio de nombres aislado. Con el fin de integrar el motor con la aplicación y compartir el mismo diseño (que puede tener ayudantes de ruta de la aplicación principal) Hice esto:

En primer lugar me eliminado config/routes.rb del motor

Entonces me quité la isolate_namespace de la clase de motores

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

he añadido un archivo que se cargó en el motor:

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 

Finalmente, en la aplicación principal de config/routes.rb en lugar de 'mount'ing el motor, puede llamar a su método

mount_my_engine_at "mount_location" 

Esto, básicamente, 'montar' su motor como parte de la aplicación principal en lugar de estar aislado de ella. Es similar a cómo lo hace Devise también.

0

La forma más fácil es dibujar las rutas tanto en la aplicación principal, y el motor, de modo que sean accesibles a la vez:

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

Puede mantener el isolate_namespace. En su routes.rb motor

MyEngine::Engine.routes.draw do 
    ... 
    root to: "something#index" 
end 

Rails.application.routes.draw do 
    get "something", to: "my_engine/something#index" 
end 

Y luego en el principal routes.rb aplicación

Rails.application.routes.draw do 

    mount MyEngine::Engine => "/anything_you_want" 

    root to: "main#index" 
end 

De esta manera usted puede elegir qué rutas desea exponer (y cuáles no)

Cuestiones relacionadas