2009-10-05 10 views
5

Buduję CMS z różnymi modułami (blog, kalendarz itp.) Za pomocą Rails 2.3. Każdy moduł jest obsługiwany przez inny kontroler i działa dobrze.Routing dynamiczny Rails oparty na bazie danych

Jedyny problem jaki mam, to główny adres URL. W zależności od konfiguracji wybranej przez użytkownika, ten domyślny adres URL powinien pokazywać inny moduł, tj. Inny kontroler, ale jedynym sposobem, w jaki muszę określić właściwy kontroler, jest sprawdzenie bazy danych pod kątem tego, który moduł "domyślny" ma zostać wyświetlony.

Na chwilę obecną używam konkretnego kontrolera "root", który sprawdza bazę danych i przekierowuje do właściwego kontrolera. Jednak wolałbym, aby adres URL nie został zmieniony, co oznacza, że ​​chcę wywołać właściwy kontroler z tego samego żądania.

Próbowałem używać Rails Metal do pobierania tych informacji i ręcznego wywoływania kontrolera, którego potrzebuję, ale myślę, że mogę wymyślać na nowo koło (identyfikuj ścieżkę żądania, aby wybrać kontroler, zarządzać sesją itp.).

Każdy pomysł? Z góry dziękuję!

Odpowiedz

5

Ten problem można rozwiązać niektóre middleware Rack:

Ten kod w 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 

Następnie w config/environment.rb na dole

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

Niniejsza middleware sprawdzi, czy Żądana strona (REQUEST_URI) to "/", a następnie wyszukaj aktualną ścieżkę (Wdrożenie do tego zależy od Ciebie ;-)). Możesz zrobić dobre na buforowanie tej informacji gdzieś (Cache.fetch('root_path') { Page.find... })

Występują problemy z sprawdzaniem REQUEST_URI, ponieważ nie wszystkie serwery internetowe przekazują je poprawnie. Dla całego szczegółach implementacji w szynach zobaczyć http://api.rubyonrails.org/classes/ActionController/Request.html#M000720 (kliknij „Pokaż źródło”)

+0

Tak, to działa! To było mniej więcej to, co już próbowałem zrobić, ale bez powodzenia aż do teraz. Dzięki Jan! –

2

W Rails 3.2 to było to, co wymyśliłem (jeszcze jako 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 

Mówi Rails, że ścieżka jest różni się od tego, co było wymagane (ścieżka root), więc odniesienia do link_to_unless_current i podobnych wciąż działają dobrze.

Załaduj middleware w tak jak w initialiser:

MyApp::Application.config.middleware.use RootRewriter 
Powiązane problemy