2010-11-17 18 views
81

Non sono riuscito a trovare una soluzione praticabile a questo problema, nonostante diverse domande simili qui e altrove. Sembra probabile che a questa domanda non sia stata data risposta per Rails 3, quindi ecco:Instradamento dei binari per gestire domini multipli su singola applicazione

Ho un'applicazione che attualmente consente agli utenti di creare il proprio sottodominio che contiene la loro istanza dell'applicazione. Mentre in Rails 2 ti è stato meglio servito usando il gemma sottodominio-fu, nella versione 3 è molto più semplice, come per Railscast - http://railscasts.com/episodes/221-subdomains-in-rails-3.

Questa è una buona cosa, ma voglio anche fornire agli utenti la possibilità di associare il proprio nome di dominio al proprio account. Quindi, anche se potrebbero avere http://userx.mydomain.com, mi piacerebbe che decidessero di avere anche lo http://userx.com associato.

Ho trovato alcuni riferimenti per farlo in Rails 2, ma quelle tecniche non sembrano funzionare più (in particolare questo: http://feefighters.com/devblog/2009/01/21/hosting-multiple-domains-from-a-single-rails-app/).

Qualcuno può consigliare un modo per utilizzare le rotte per accettare un dominio arbitrario e trasmetterlo a un controller in modo da poter mostrare il contenuto appropriato?

Aggiornamento: Ho ottenuto la maggior parte di una risposta ora, grazie alla tempestiva risposta di Leonid, e una nuova occhiata al codice. Alla fine ha richiesto un'aggiunta al codice del sottodominio esistente che stavo usando (dalla soluzione Railscast) e quindi aggiungendo un po 'a routes.rb. Non sono ancora arrivato, ma voglio pubblicare ciò che ho finora.

in 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 

Ho aggiunto la seconda classe a imitazione del primo, che è noto di lavoro. Aggiungo semplicemente una condizione che garantisce che il dominio in ingresso non sia quello per il quale sto ospitando il sito principale.

Questa classe viene utilizzata in routes.rb:

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

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

qui, sono anteponendo il codice sottodominio esistente (ancora una volta, sta funzionando benissimo) con una strofa di controllare per il dominio. Se questo server risponde a quel dominio e non è quello in cui opera il sito principale, inoltrare al controller specificato.

E mentre sembra funzionare, non ho ancora tutto funzionante, ma penso che questo particolare problema sia stato risolto.

+1

Grazie mille per la tua modifica, Aaron. Ho a che fare con la stessa identica situazione in questo momento. Come domanda successiva, come si ottiene che il server accetti qualsiasi dominio che viene inoltrato ad esso? Presumo che sarebbe un'impostazione nel file .conf, ma non sono sicuro di cosa.Qualsiasi aiuto sarebbe apprezzato! – deadwards

+0

Aaron, sono con te. Voglio fare la stessa cosa Ma non voglio hardcode il dominio. Voglio tutto fatto a livello di programmazione senza file di zona e il server Web si riavvia. –

+1

Michael, devi capovolgere il problema. Dichiara esplicitamente e hardcode le rotte che sono esclusivamente per la tua applicazione (ad es. Iscrizioni) con un vincolo host o sottodominio, quindi considera i tuoi percorsi principali come "qualsiasi dominio o sottodominio". È quindi responsabilità dei tuoi controllori cercare il dominio o sottodominio corrente e mapparlo al cliente giusto. –

risposta

88

In realtà è più semplice in Rails 3, come da http://guides.rubyonrails.org/routing.html#advanced-constraints:

1) definire una classe vincolo personalizzata in lib/domain_constraint.rb:

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

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

2) utilizzare la classe nei tuoi percorsi con la nuova sintassi del blocco

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

root :to => 'main#index' 

o la sintassi opzione di vecchio stile

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

Grazie per la tua risposta ... Avevo perso la speranza! Ma guardando questo codice, sembra che ho bisogno di anticipare il dominio utilizzato. Voglio usare qualsiasi dominio arbitrario. Ma ora ho scoperto la risposta (principalmente), quindi modificherò la mia domanda sopra. –

+0

Perché dichiarare la classe in un inizializzatore? Non dovrebbe essere in lib? – ybakos

+0

Sì, dovrebbe essere in lib. –

Problemi correlati