2009-10-05 10 views
5

Je construis un CMS avec divers modules (blog, calendrier, etc.) en utilisant Rails 2.3. Chaque module est géré par un contrôleur différent et cela fonctionne très bien.Routage de Rails dynamiques basé sur la base de données

Le seul problème que j'ai est avec l'URL racine. Selon la configuration choisie par l'utilisateur, cette URL par défaut devrait montrer un module différent, c'est-à-dire un contrôleur différent, mais la seule façon de déterminer le bon contrôleur est de vérifier la base de données pour le module "par défaut".

Pour l'instant j'utilise un contrôleur "racine" spécifique qui vérifie la base de données et redirige vers le contrôleur correct. Cependant, je préférerais que l'URL ne soit pas modifiée, ce qui signifie que je veux invoquer le bon contrôleur à partir de la même requête. J'ai essayé d'utiliser Rails Metal pour récupérer cette information et appeler manuellement le contrôleur que je veux mais je pense que je peux réinventer la roue (identifier le chemin de la demande pour choisir le contrôleur, gérer la session, etc.).

Une idée? Merci beaucoup d'avance!

Répondre

5

Ce problème peut être résolu avec un certain middleware Rack:

Ce code 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 

Puis dans votre config/environment.rb au fond

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

Ce middleware vérifiera si la la page demandée (REQUEST_URI) est '/' et ensuite faire une recherche pour le chemin réel (l'implémentation à ceci est à vous ;-)). Vous pouvez faire du bon sur la mise en cache de cette info quelque part (Cache.fetch('root_path') { Page.find... })

Il ya quelques problèmes avec la vérification REQUEST_URI, car tous les serveurs Web ne passent pas correctement. Pour l'ensemble de détails de mise en œuvre Rails voir http://api.rubyonrails.org/classes/ActionController/Request.html#M000720 (Cliquez sur « Afficher la source »)

+0

Oui, cela fonctionne! C'était plus ou moins ce que j'essayais déjà de faire, mais sans succès jusqu'à présent. Merci, Jan! –

2

Dans Rails 3.2, ceci est ce que je suis venu avec (encore 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 

Cela indique Rails que le chemin est différent de ce qui a été demandé (le chemin racine), donc les références à link_to_unless_current et similaires fonctionnent encore bien.

Chargez le middleware comme si dans un initialiseur:

MyApp::Application.config.middleware.use RootRewriter 
Questions connexes