2009-10-05 15 views
5

Sto costruendo un CMS con vari moduli (blog, calendario, ecc.) Utilizzando Rails 2.3. Ogni modulo è gestito da un controller diverso e funziona perfettamente.Routing Dynamic Rails basato sul database

L'unico problema che ho è con l'URL di root. A seconda della configurazione scelta dall'utente, questo URL predefinito dovrebbe mostrare un modulo diverso, ad esempio un controller diverso, ma l'unico modo per determinare il controller corretto è controllare il database per quale modulo "predefinito" deve essere mostrato.

Per il momento sto utilizzando uno specifico controller "root" che controlla il database e reindirizza al controller corretto. Tuttavia preferirei che l'URL non venga modificato, il che significa che voglio richiamare il controller corretto dalla stessa richiesta.

Ho provato a utilizzare Rails Metal per recuperare queste informazioni e chiamare manualmente il controller che desidero, ma penso che potrei reinventare la ruota (identificare il percorso della richiesta per scegliere il controller, gestire la sessione, ecc.).

Qualche idea? Grazie mille in anticipo!

risposta

5

Questo problema può essere risolto con un po 'Rack middleware:

Questo codice in 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 

Poi, nel tuo config/environment.rb in fondo

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

Questo middleware controllerà se il la pagina richiesta (REQUEST_URI) è '/' e quindi effettua una ricerca per il percorso effettivo (l'implementazione di questo dipende da te ;-)). Si potrebbe fare del bene nella cache di queste informazioni da qualche parte (Cache.fetch('root_path') { Page.find... })

Ci sono alcuni problemi con il controllo di REQUEST_URI, poiché non tutti i server web lo superano correttamente. Per tutto il dettaglio di implementazione in Rails vedere http://api.rubyonrails.org/classes/ActionController/Request.html#M000720 (Fai clic su "Visualizza sorgente")

+0

Sì, questo funziona! Questo era più o meno quello che stavo già cercando di fare, ma senza successo fino ad ora. Grazie Jan! –

2

In Rails 3.2 questo era quello che mi si avvicinò con (ancora 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 

Questo dice Rails che il percorso sia diverso da quello che è stato richiesto (il percorso root) quindi i riferimenti a link_to_unless_current e simili funzionano ancora bene.

Caricare il middleware in questo modo in un initialiser:

MyApp::Application.config.middleware.use RootRewriter