2009-10-05 27 views
5

Estoy construyendo un CMS con varios módulos (blog, calendario, etc.) utilizando Rails 2.3. Cada módulo es manejado por un controlador diferente y funciona bien.Enrutamiento de Dynamic Rails basado en la base de datos

El único problema que tengo es con la URL raíz. Dependiendo de la configuración elegida por el usuario, esta URL predeterminada debe mostrar un módulo diferente, es decir, un controlador diferente, pero la única forma que tengo de determinar el controlador correcto es verificando en la base de datos qué módulo "predeterminado" se mostrará.

Por el momento estoy usando un controlador "raíz" específico que comprueba la base de datos y redirige al controlador correcto. Sin embargo, preferiría que la URL no se cambiara, lo que significa que quiero invocar el controlador correcto desde la misma solicitud.

He intentado utilizar Rails Metal para buscar esta información y llamar manualmente al controlador que quiero, pero estoy pensando en reinventar la rueda (identificar la ruta de solicitud para elegir el controlador, gestionar la sesión, etc.).

¿Alguna idea? ¡Muchas gracias por adelantado!

Respuesta

5

Este problema se puede resolver con un poco de estante de middleware:

este código en lib/root_rewriter.rb:

module DefV 
    class RootRewriter 
    def initialize(app) 
     @app = app 
    end 

    def call(env) 
     if env['REQUEST_URI'] == '/' # Root is requested! 
     env['REQUEST_URI'] = Page.find_by_root(true).uri # for example /blog/ 
     end 

     @app.call(env) 
    end 
    end 
end 

Luego, en su config/environment.rb en la parte inferior

require 'root_rewriter' 
ActionController::Dispatcher.middleware.insert_after ActiveRecord::QueryCache, DefV::RootRewriter 

Este middleware comprobará si el La página solicitada (REQUEST_URI) es '/' y luego busca el camino real (la implementación depende de ti ;-)). Puede ser útil almacenar en caché esta información en algún lugar (Cache.fetch('root_path') { Page.find... })

Existen algunos problemas al verificar REQUEST_URI, ya que no todos los servidores web pasan esto correctamente. Para todo el detalle de implementación en los carriles ver http://api.rubyonrails.org/classes/ActionController/Request.html#M000720 (Haga clic en "Ver código fuente")

+0

Sí, esto funciona! Esto era más o menos lo que ya estaba tratando de hacer, pero sin éxito hasta ahora. Gracias Jan! –

2

En Rails 3.2 esto fue lo que me ocurrió con (todavía un middleware):

class RootRewriter 
    def initialize(app) 
    @app = app 
    end 

    def call(env) 
    if ['', '/'].include? env['PATH_INFO'] 
     default_thing = # Do your model lookup here to determine your default item 
     env['PATH_INFO'] = # Assemble your new 'internal' path here (a string) 
     # I found useful methods to be: ActiveModel::Naming.route_key() and to_param 
    end 

    @app.call(env) 
    end 
end 

Esto le dice a Rails que el camino es diferente de lo que se solicitó (la ruta raíz) por lo que las referencias a link_to_unless_current y similares todavía funcionan bien.

de carga en el middleware como tal en un inicializador:

MyApp::Application.config.middleware.use RootRewriter 
Cuestiones relacionadas