2010-11-17 6 views
81

J'ai été incapable de trouver une solution réalisable à ce problème, malgré plusieurs questions similaires ici et ailleurs. Il semble probable que cette question n'a pas été répondu pour Rails 3, alors voiciRails routage pour gérer plusieurs domaines sur une seule application

J'ai une application qui permet actuellement aux utilisateurs de créer leur propre sous-domaine qui contient leur instance de l'application. Alors que dans Rails 2, vous étiez mieux servi en utilisant la sous-gemme subdomain-fu, dans la version 3, c'est beaucoup plus simple, selon le Railscast - http://railscasts.com/episodes/221-subdomains-in-rails-3.

C'est une bonne chose, mais je veux aussi donner aux utilisateurs la possibilité d'associer leur propre nom de domaine à leur compte. Donc, alors qu'ils pourraient avoir http://userx.mydomain.com, je voudrais qu'ils choisissent d'avoir aussi http://userx.com.

J'ai trouvé quelques références à faire cela dans Rails 2, mais ces techniques ne semblent plus fonctionner (en particulier celle-ci: http://feefighters.com/devblog/2009/01/21/hosting-multiple-domains-from-a-single-rails-app/).

Quelqu'un peut-il recommander un moyen d'utiliser des routes pour accepter un domaine arbitraire et le transmettre à un contrôleur afin que je puisse afficher le contenu approprié?

Mise à jour: J'ai reçu la plupart des réponses maintenant, grâce à la réponse rapide de Leonid, et un nouveau regard sur le code. Il a finalement exigé un ajout au code Subdomain existant que j'utilisais (à partir de la solution Railscast), puis en ajoutant un bit à routes.rb. Je ne suis pas encore là mais je veux poster ce que j'ai jusqu'ici.

Dans lib/subdomain.rb:

class Subdomain 
    def self.matches?(request) 
    request.subdomain.present? && request.subdomain != "www" 
    end 
end 

class Domain 
    def self.matches?(request) 
    request.domain.present? && request.domain != "mydomain.com" 
    end 
end 

J'ai ajouté la deuxième classe à l'imitation de la première, qui est connu de travail. J'ajoute simplement une condition qui garantit que le domaine entrant n'est pas celui pour lequel j'héberge le site principal.

Cette classe est utilisée dans routes.rb:

require 'subdomain' 
constraints(Domain) do 
    match '/' => 'blogs#show' 
end 

constraints(Subdomain) do 
    match '/' => 'blogs#show' 
end 

Ici, je suis préfixer le code existant sous-domaine (encore une fois, il fonctionne très bien) avec une strophe pour vérifier le domaine. Si ce serveur répond à ce domaine et n'est pas celui sous lequel le site principal fonctionne, transmettez-le au contrôleur spécifié.

Et même si cela semble fonctionner, je n'ai pas encore tout à fait fonctionné, mais je pense que ce problème particulier a été résolu.

+1

Merci beaucoup pour votre montage, Aaron. Je fais face à la même situation en ce moment. À titre de question complémentaire, comment obtenez-vous que votre serveur accepte tout domaine qui lui est transféré? Je suppose que ce serait un paramètre dans le fichier .conf, mais je ne suis pas sûr de quoi.Toute aide serait appréciée! – deadwards

+0

Aaron, je suis avec toi. je veux faire la même chose. Mais je ne veux pas coder en dur le domaine. Je veux que tout soit fait par programme sans les fichiers de zone et les redémarrages du serveur web. –

+1

Michael, vous devez retourner le problème. Déclarer explicitement et coder en dur les routes qui sont exclusivement destinées à votre application (par exemple en vous inscrivant) avec une contrainte d'hôte ou de sous-domaine, puis traiter vos routes principales comme "n'importe quel domaine ou sous-domaine". Il incombe alors à vos contrôleurs de rechercher le domaine ou le sous-domaine actuel et de le mapper au bon client. –

Répondre

88

Il est en fait plus simple dans Rails 3, selon http://guides.rubyonrails.org/routing.html#advanced-constraints:

1) définissent une classe de contrainte personnalisée dans lib/domain_constraint.rb:

class DomainConstraint 
    def initialize(domain) 
    @domains = [domain].flatten 
    end 

    def matches?(request) 
    @domains.include? request.domain 
    end 
end 

2) utiliser la classe dans vos itinéraires avec la nouvelle syntaxe du bloc

constraints DomainConstraint.new('mydomain.com') do 
    root :to => 'mydomain#index' 
end 

root :to => 'main#index' 

ou l'option ancienne syntaxe

root :to => 'mydomain#index', :constraints => DomainConstraint.new('mydomain.com') 
+0

Merci pour votre réponse ... J'avais perdu espoir! Mais en regardant ce code, il semble que je devrais anticiper le domaine utilisé. Je veux utiliser n'importe quel domaine arbitraire. Mais j'ai maintenant découvert la réponse (surtout), alors je vais éditer ma question ci-dessus. –

+0

Pourquoi déclarer la classe dans un initialiseur? Cela ne devrait-il pas être lib? – ybakos

+0

Oui, ça devrait être dans lib. –

Questions connexes