2009-10-05 15 views
5

Ich baue ein CMS mit verschiedenen Modulen (Blog, Kalender, etc.) mit Rails 2.3. Jedes Modul wird von einem anderen Controller verwaltet und das funktioniert gut.Dynamisches Rails Routing basierend auf Datenbank

Das einzige Problem, das ich habe, ist mit der Stamm-URL. Abhängig von der vom Benutzer gewählten Konfiguration sollte diese Standard-URL ein anderes Modul zeigen, d.h. einen anderen Controller, aber die einzige Art, den richtigen Controller zu bestimmen, besteht darin, die Datenbank zu überprüfen, welches "Standard" -Modul angezeigt werden soll.

Für den Moment verwende ich einen bestimmten "root" Controller, der die Datenbank überprüft und an den richtigen Controller umleitet. Allerdings würde ich bevorzugen, dass die URL nicht geändert wird, was bedeutet, dass ich den richtigen Controller von derselben Anfrage aufrufen möchte.

Ich habe versucht, Rails Metal zu verwenden, um diese Informationen abzurufen und manuell den Controller aufzurufen, den ich möchte, aber ich denke, ich erfinde das Rad neu (identifizieren Sie den Anforderungspfad, um den Controller auszuwählen, Sitzung zu verwalten usw.).

Irgendeine Idee? Vielen Dank im Voraus!

Dieser Code in lib/root_rewriter.rb: überprüfen, ob die

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 

Dann Diese Middleware wird am unteren

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

in Ihrem config/environment.rb

Antwort

5

Dieses Problem kann mit einiger Rack-Middleware gelöst werden angeforderte Seite (REQUEST_URI) ist '/' und dann suche nach dem tatsächlichen Pfad (Die Implementierung bleibt Ihnen überlassen ;-)). Sie könnten diese Info irgendwo zwischenspeichern (Cache.fetch('root_path') { Page.find... })

Es gibt einige Probleme mit der Überprüfung REQUEST_URI, da nicht alle Webserver diese richtig übergeben. Für die gesamte Implementierung Detail in Rails sehen http://api.rubyonrails.org/classes/ActionController/Request.html#M000720 (Klicken Sie auf "Quelltext anzeigen")

+0

Ja, das funktioniert! Das war mehr oder weniger das, was ich bereits versuchte, aber bisher ohne Erfolg. Danke Jan! –

2

In Rails 3.2 das war, was ich mit (noch eine Middleware) kam:

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 

Dies sagt Rails dass der Weg ist unterscheidet sich von dem, was angefordert wurde (der Root-Pfad), so dass Referenzen auf link_to_unless_current und dergleichen immer noch gut funktionieren.

Legen Sie die Middleware in etwa so in einem initialiser:

MyApp::Application.config.middleware.use RootRewriter