2010-11-17 13 views
81

No he podido encontrar una solución viable para este problema, a pesar de varias preguntas similares aquí y en otros lugares. Parece probable que esta pregunta no haya sido respondida para Rails 3, así que aquí va:Enrutamiento de rieles para manejar varios dominios en una sola aplicación

Tengo una aplicación que actualmente permite a los usuarios crear su propio subdominio que contiene su instancia de la aplicación. Mientras que en Rails 2 fue mejor ser servido usando la gema subdomain-fu, en la versión 3 es dramáticamente más simple, según el Railscast - http://railscasts.com/episodes/221-subdomains-in-rails-3.

Eso es bueno, pero también quiero ofrecer la opción para que los usuarios asocien su propio nombre de dominio con su cuenta. Así que, aunque podrían tener http://userx.mydomain.com, me gustaría que también eligieran http://userx.com como asociados.

Encontré algunas referencias para hacer esto en Rails 2, pero esas técnicas ya no parecen funcionar (particularmente esta: http://feefighters.com/devblog/2009/01/21/hosting-multiple-domains-from-a-single-rails-app/).

¿Alguien puede recomendar una forma de usar rutas para aceptar un dominio arbitrario y pasarlo a un controlador para que pueda mostrar el contenido apropiado?

Actualización: He obtenido la mayor parte de la respuesta ahora, gracias a la respuesta oportuna de Leonid, y una nueva mirada al código. Finalmente requirió una adición al código de Subdominio existente que estaba usando (de la solución de Railscast) y luego agregó un bit a routes.rb. Todavía no llegué allí, pero quiero publicar lo que tengo hasta ahora.

en 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 

He añadido la segunda clase en la imitación de la primera, que se conoce de trabajo. Simplemente agrego una condición que asegura que el dominio entrante no sea el que estoy hospedando en el sitio principal.

Esta clase se utiliza en routes.rb:

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

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

aquí, estoy anteponiendo el código subdominio existente (de nuevo, está funcionando bien) con una estrofa para comprobar el dominio. Si este servidor responde a ese dominio y no es bajo el cual opera el sitio principal, reenvíelo al controlador especificado.

Y aunque eso parece estar funcionando, todavía no lo tengo todo funcionando, pero creo que este problema en particular se ha resuelto.

+1

Muchas gracias por su edición, Aaron. Estoy lidiando con la misma situación en este momento. Como pregunta de seguimiento, ¿cómo logra que su servidor acepte cualquier dominio que se le envíe? Supongo que sería una configuración en el archivo .conf, pero no estoy seguro de qué.¡Cualquier ayuda sería apreciada! – deadwards

+0

Aaron, estoy contigo. Quiero hacer lo mismo. Pero no quiero codificar el dominio. Lo quiero todo hecho programáticamente sin archivos de zona y reinicios del servidor web. –

+1

Michael, necesitas voltear el problema. Declare y codifique explícitamente las rutas que son exclusivas para su aplicación (por ejemplo, registro) con una restricción de host o subdominio, luego trate sus rutas principales como "cualquier dominio o subdominio". Es responsabilidad de los controladores buscar el dominio o subdominio actual y asignarlo al cliente correcto. –

Respuesta

88

En realidad es más simple en los carriles 3, según http://guides.rubyonrails.org/routing.html#advanced-constraints:

1) definir una clase de restricción de costumbre en lib/domain_constraint.rb:

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

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

2) utilizar la clase en sus rutas con la nueva sintaxis del bloque

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

root :to => 'main#index' 

o la sintaxis de la opción antigua

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

Gracias por su respuesta ... ¡Había perdido la esperanza! Pero al mirar este código, parece que tengo que anticiparme al dominio que se está utilizando. Quiero usar cualquier dominio arbitrario. Pero ahora descubrí la respuesta (principalmente), por lo que voy a editar mi pregunta anterior. –

+0

¿Por qué declararías la clase en un inicializador? ¿No debería ser eso lib? – ybakos

+0

Sí, debería estar en lib. –

Cuestiones relacionadas